DIP 1016--ref T accepts r-values--Formal Assessment

kinke noone at nowhere.com
Thu Jan 24 21:03:29 UTC 2019

On Thursday, 24 January 2019 at 09:04:41 UTC, Nicholas Wilson 
> On Thursday, 24 January 2019 at 07:18:58 UTC, Mike Parker wrote:
>> The second problem is the use of := (which the DIP Author 
>> defines as representing "the initial construction, and not a 
>> copy operation as would be expected if this code were written 
>> with an = expression"). This approach shows its deficiencies 
>> in the multiple arguments case; if the first constructor 
>> throws an exception, all remaining values will be destroyed in 
>> the void state as they never have the chance to become 
>> initialized.
> Although not specified by the DIP, I think this could be easily 
> remedied by saying that the order of construction is the same 
> as if the temporaries were not bound to ref, i.e.
> ---
> struct A {~this();} struct B{ ~this();}
> A a();
> B b();
> void f(A a, B b);
> void g(ref A a, ref B b);
> f(a(),b());  //(1)
> g(a(),b()); //(2)
> ---
> and a() or b() may throw (and are pure), that (1) and (2) 
> exhibit the same exception/destructor semantics.

Describing this stuff in detail (rewritten expression?!), isn't 
trivial and requires knowledge about how calls and 
construction/destruction of argument expressions works.
E.g., the f() call in the code above is lowered to (-vcg-ast):

(bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy = b();)) 
, __gate = true , f(__pfx, __pfy);

Here, (only seemingly unused) temporary `__gate` is used to 
control the destruction of temporaries with dtors (here just the 
`__pfx` arg, as `__pfy` is a special case [no potentially 
throwing later argument expressions...]) at the caller side 
(false => destruct; true => skip destruction, as it has been 
moved successfully to the callee, which destructed it). The dtor 
expressions of these temporaries (e.g., `__gate || __pfx.~this()` 
for `__pfx`) aren't visible with `-vg-ast`.

With this DIP, *all* rvalues passed by ref must be lowered to 
temporaries. In case they require destruction, the only 
difference wrt. the by-value case is that they are *always* 
destructed by the caller (after the call, or if an exception is 
thrown while they are in scope), i.e., their destruction isn't 
controlled by `__gate`.

More information about the Digitalmars-d-announce mailing list