On Monday, 28 January 2019 at 19:58:24 UTC, Andrei Alexandrescu wrote:
On 1/28/19 1:00 PM, Andrei Alexandrescu wrote:
It seems to me that a proposal adding the "@rvalue" attribute in function signatures to each parameter that would accept either an rvalue or an lvalue would be easy to argue.

- No exposing existing APIs to wrong uses
- The function's writer makes the decision ("I'm fine with this function taking an rvalue")
- Appears in the function's documentation
- Syntax is light and localized where it belongs
- Scales well with number of parameters
- Transparent to callers

The inverse, the @norval attribute, would feature all but the first advantages, at least once people get used to normal ref allowing (some) rvalues too. I can't think of many good reasons for a callee to disallow rvalues (with matching type at least); your example wrt. interlockedIncrement() is a good one, as synchronization overhead clearly isn't required for an rvalue. But my usages of (mutable) ref are >99% of the time something like:

Header readHeader(ref Stream stream)
{
    // read from & advance stream, return parsed header
}

where I'd like to be able put everything into one line if trivial (stream not required later on):

readHeader(Stream("file")).doSomething();

(And const ref is mostly used for performance with bigger structs, where rvalues are absolutely fine).

TLDR: I'd guess that I'd need to type `@rvalue` about 1000 times as often as `@norval`. I'm not kidding.

TL;DR: it could be argued that the only dangerous conversions are lvalue -> temp rvalue -> ref, so only disable those. The conversion rvalue -> temp rvalue -> ref is not dangerous because the starting value on the caller side could not be inspected after the call anyway.

I agree that the DIP needs to be clearer wrt. rvalues resulting from implicit conversions. I also agree with the above point. I'm just not sure we need to allow implicit conversions from rvalue argument expressions at all. To minimize the changes for overload resolution, it might be enough to allow rvalue argument expressions of matching type only, i.e., the types which are allowed for current ref semantics. After all, I don't plan to use the proposed ref semantics for primitive types where that might come in handy (something silly like `modf(x, 123.456)` if the second param is a `ref real`), and explicit casts would IMO be an acceptable price to pay for safety and visibility in the remaining cases.

Reply via email to