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.

Reply via email to