[dmd-beta] rvalue references

Andrei Alexandrescu andrei at erdani.com
Wed Apr 11 18:55:53 PDT 2012


Answers within.

On 4/11/12 6:53 AM, Steve Schveighoffer wrote:
> --------------------------
> Issue 1:
>
> In TDPL, you say:
>
> for context:
> void bump(ref int x) {++x;}
>
> "If a function expects a ref, it accepts only "real" data, not
> temporaries; anything that's not an lvalue is rejected during
> compilation; for example:
>
> bump(5); // Error! Cannot bind an rvalue to a ref parameter
>
> This prevents silly mistakes when people believe work is being done but
> in fact the call has no visible affect."
>
> This is in section 5.2.1
>
> Now, this obviously becomes valid code. Are you OK with this? It seemed
> like a major explanation as to why refs don't bind to rvalues. I
> personally think it's just "coder beware".
>
> -----------------------------

The example in the book rehashes the old example by Bjarne Stroustrup in 
his TC++PL book. The danger is there but in a slightly different form. 
Consider:

short x;
bump(x);

*This* is the wrong/dangerous code because it silently increments a 
temporary generated from x, whereas the user may think it increments x. 
On the other hand, the code

bump(5);

is less dangerous because the user is unlikely to believe they 
incremented the literal 5 such that writing 5 again will actually mean 
6! (Crazy as it sounds, something like that happens in Smalltalk. Ew.)

So converting rvalues to references is fine AS LONG AS the rvalues don't 
originate from lvalues of a different type.

> Issue 2:
>
> Another reason I remember you stating as to why rvalues cannot bind to
> ref is that it's not the most efficient semantics. So if rvalues bind to
> both non-ref and ref, can you have overloads between ref and non-ref for
> optimization purposes?
>
> Note that this is *valid* code with 2.058 (and probably many previous
> compilers):
>
> import std.stdio;
>
> void foo(ref int x) { writeln("ref"); }
> void foo(int x) { writeln("nonref"); }
>
> void main()
> {
> int x;
> foo(x);
> foo(5);
> }
>
> prints:
> ref
> nonref
>
> Will this still compile under the new rules, or will it be ambiguous?
>
> -----------------------------

This code should continue to compile under the new rules. A library 
writer should be able to distinguish rvalues from lvalues.

> Issue 3:
>
> The point that you cannot take an address of a ref value is going to
> cause a *lot* of existing code to fail. I don't really like this rule
> for code that isn't marked @safe (which should disallow taking addresses
> anyway). It seems overly restrictive, and it will be viral in nature. I
> know you mentioned this is the "long term plan", are the other parts of
> this severable from this? Is the plan to implement this right now or
> later? Can you explain why the existing requirements that you don't use
> pointers in @safe code isn't enough?
>
> -Steve
>
>
> _______________________________________________

It is true that the new rule will break code. Walter and I assess that 
the amount of breakage will be, however, small. Even in today's C++ it 
is poor style to take the address of reference variables and sneak the 
resulting pointer. Though sometimes this is necessary in C++, we think 
it already is much less so in D.

Walter likes the idea that we first introduce the restriction in @safe 
code alone. I think we must eventually introduce it for all code, and my 
understanding is that Walter is also convinced of that.


Andrei


More information about the dmd-beta mailing list