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`.

Reply via email to