[dmd-beta] rvalue references

Walter Bright walter at digitalmars.com
Tue Apr 10 17:57:01 PDT 2012


I couldn't remember what the big problem was with rvalue references, and so I 
spent some time on the phone talking with Andrei about what exactly the problem 
is. They are:

1.
C++:
   int i;
   double& d = i;
   ++d;

The problem is that i is implicitly converted to a double, and then the address 
is taken and assigned to d. When what d refers to is incremented, it increments 
the temporary, and i is inexplicably left untouched. I say inexplicably because 
when an implicit conversion happens isn't always obvious to the user. C++ is 
full of implicit conversions, so these types of silent bugs crop up.

This one isn't too bad, you could say "just make it a const&", but consider the 
related:

2.
   double& d;
   int i;
   void foo() {
     d = i;
   }

Now d is referring to a temporary that has gone out of scope. This is, of 
course, a memory corrupting disaster, const ref or no const.

3. This one is a more general problem with references, that of escaping 
references to locals:
   double& d;
   void foo(double x, double y) {
      d = x + y;
   }

OMG LOL big oops, we've now got a reference to a temporary that goes out of scope.

---------------------------------------------
Our D solution, disallowing rvalue references, is technically sound but as we've 
discussed here is a usability disaster, and auto ref isn't going to cut it. We 
figured a solution is:

*** Allow rvalue references, however, disallow any implicit conversions of the 
literal's type in the process of taking a reference to it. ***

That takes care of 1 and 2. The solution to 3 is a bit more subtle. Some people 
have wondered why the D compiler can create reference types itself, but does not 
allow the user to outside of function parameters and foreach variables. This is 
the reason why. References, in order to be safe, must not be allowed to escape a 
scope. They can only be passed downward to enclosed scopes, and returned from 
functions where the return value is checked. Also, one cannot take the address 
of a reference. I think this closes the holes.

With all that, I intend to once again allow struct literals to be lvalues for 
2.059. Somewhat later, also allow references to other literals like 0 and 5.6.


More information about the dmd-beta mailing list