On Thursday, 24 January 2019 at 09:04:41 UTC, Nicholas Wilson
wrote:
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`.