DIP 1016--ref T accepts r-values--Formal Assessment
Walter Bright
newshound2 at digitalmars.com
Fri Jan 25 11:56:58 UTC 2019
On 1/24/2019 11:53 PM, Nicholas Wilson wrote:
> That the conflation of pass by reference to avoid copying and mutation is not
> only deliberate but also mitigated by @disable.
The first oddity about @disable is it is attached to the foo(int), not the
foo(ref int). If I wanted to know if foo(ref int) takes rvalue references, I'd
have to go looking for the existence of another function. This is one of those
cases where it's hard to prove a negative, as other functions can be introduced
by mixins. This is a strong usability negative.
Next, the @disable applies to the entire parameter list. However, overload
selection is done by looking at each parameter. The DIP says:
"The DIP author responded that ideas to improve this are welcome, but that he
cannot imagine a use case."
I can guarantee that the use case of more than one reference parameter will come
up. The workarounds the DIP suggests are simply awful.
Let's look at what C++ does for rvalue references:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html
The syntax is attached to the parameter declaration of the function it applies
to, not some other function, and not every parameter:
int foo(T&& t); // C++ rvalue ref
There are no weird workarounds, at least for that aspect. There are indeed
unlikable things about the C++ rules, but the DIP needs to pay more attention to
how C++ does this, and justify why D differs. Particularly because D will likely
have to have some mechanism of ABI compatibility with C++ functions that take
rvalue references.
This is not a small problem.
A further problem is implicit conversions, which the DIP ignores by only talking
about ints.
void bar(int);
void foo(ref int);
enum short s = 10;
bar(s); // compiles
foo(s); // currently fails to compile
Should `s` be promoted to an int temporary, then pass the temporary by
reference? I can find no guidance in the DIP. What if `s` is a uint (i.e. the
implicit conversion is a type paint and involves no temporary)?
Here's a discussion of Rust and rvalue references which may offer insight:
https://www.reddit.com/r/rust/comments/3ko5pm/explaining_cs_rvalue_references_from_a_rust/
> That the DIP applies to statements, not expressions.
The DIP should not invent its own syntax, give no explanation of it, and have
the reader guess. (It did explain the :=, but not the use of { } and
statements.) And, even if one did a mental rewrite, the semantics of the
statement version are simply wrong. (For example, if 'fun' was actually a
function pointer returned by another function, and that other function threw an
exception - then the destructor would be run on an uninitialized variable.)
> That the construction order issue is trivially fixable, by specifying the same
> behaviour as the non ref case modulo ref.
It should never have gotten this far without giving a precise explanation of how
exception safety is achieved when faced with multiple parameters. In the past
I've done a lot of work on exception safety, and it isn't trivial once one goes
beyond trivial cases.
All that criticism aside, I'd like to see rvalue references in D. But the DIP
needs significant work.
More information about the Digitalmars-d-announce
mailing list