How do I overload a proc to take either an immutable T or a sink T?
Something like
proc f(s: string) =
echo "s is immutable"
proc f(s: sink string) =
echo "control taken"
discard move(s)
current output:
Error: ambiguous call
if a variable is passed to the proc that accepts a sink argument and it's not the last use, Nim just makes a copy
That's what I want to prevent. How do I tell it to either take the ownership or to call it with an immutable argument, without making a copy?
Just have a feeling that a layer is missing.
For example if you only need a part of data, taking the control of the buffer would be most efficient, while copying the data you need is less efficient, but still more efficient than copying the whole buffer. But with sink T, you'll either take the ownership, or copy it all.
if a variable is passed to the proc that accepts a sink argument and it's not the last use, Nim just makes a copy
Overloading by sink T has been left out by design. What is your use case?
The better question here is: "when would I not want to type sink for every parameter?"
Since sink automatically discards itself and always makes a copy when needed, there's no case where I would not want to type sink because the non-sink version is either worse or the same. At this point it becomes pointless noise.
there's no case where I would not want to type sink because the non-sink version is either worse or the same.
I believe it wasn't true. If you look at the resulted C code, you'll see that =copy is called whenever a sink-proc is called, except being the last time a parameter is used. But when it's a proc with immutable parameter being called, =copy is not invoked, as the arguments are expected not to be changed. That's why I've tried to overload it.
The better question here is: "when would I not want to type sink for every parameter?"
Almost always since usually no ownership change is required. sink T propagates "need a copy here" up the call chain. If you don't need a copy (which is almost always), don't use sink. It's like in C++ passing by const T& vs by value T. Or in Rust borrow vs consume.
If overloading with sink T is to be supported. The symbol resolving order should be:
sink T/=sink > var T > T > sink T/=copy
Making a copy should be the last option, as it's most inefficient.