[dmd-beta] rvalue references

Steve Schveighoffer schveiguy at yahoo.com
Thu Apr 12 04:33:31 PDT 2012


More responses within ;)




>________________________________
> From: Andrei Alexandrescu <andrei at erdani.com>
>
>
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.
>
Ok, this makes sense.  Again, I was playing devil's advocate here ;)

Some more arguments from the prince of darkness:  What about properties?  We now will have this possibility:

x.y++; // y is an rvalue property

or at least

bump(x.y);

My thought is that the compiler really has no way to determine if the property is an effective lvalue (i.e. a range which has references in it, but itself is not really an lvalue), so restricting this for the benefit of preventing such situations is not worth the damage to other valid situations.


> 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.
>
>Excellent!


>> 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.
>
>
My largest concern is with &this, as you outlined.  Since you cannot specify that a method accepts 'this' as a pointer, it's almost impossible to write methods for things like linked lists.

However, due to the advent of UFCS, I see some light at the end of the tunnel.  In any case, we *must* have a way to override this behavior, if it's not allowed even in un- at safe code.  If it's restricted to @safe code, we need no workaround, the code is clearly un- at safe.



>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.
>This is good, I think it's the right path.  My opinion is that it only belongs in @safe code.

One other issue I just thought of that's related to this is delegates.  A delegate to a struct member function effectively stores a reference to the instance, will it be allowed?  Perhaps only as a scope parameter?  I think not allowing this would be a crippling restriction, but allowing it would make this rule have a lot less teeth.


-Steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/dmd-beta/attachments/20120412/fb00c880/attachment.html>


More information about the dmd-beta mailing list