digitalmars.D.internals - Enable more pass-by-move of structs
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (92/92) Oct 26 2018 I'm trying to figure out how to enable more pass-by-move of
I'm trying to figure out how to enable more pass-by-move of structs in cases such as struct S { disable this(this); double x, y; } void f() { S a; S b = a; // pass by move for final ref of `a` in `a`'s scope } . The motivation for this has been approved by andralex and is described and discussed at https://github.com/dlang/phobos/pull/4971. AFAICT, the block if (e2x.isLvalue()) { if (!e2x.type.implicitConvTo(e1x.type)) { exp.error("conversion error from `%s` to `%s`", e2x.type.toChars(), e1x.type.toChars()); return setError(); } /* Rewrite as: * (e1 = e2).postblit(); * * Blit assignment e1 = e2 returns a reference to the original e1, * then call the postblit on it. */ Expression e = e1x.copy(); e.type = e.type.mutableOf(); if (e.type.isShared && !sd.type.isShared) e.type = e.type.unSharedOf(); e = new BlitExp(exp.loc, e, e2x); e = new DotVarExp(exp.loc, e, sd.postblit, false); e = new CallExp(exp.loc, e); result = e.expressionSemantic(sc); return; } else { /* The struct value returned from the function is transferred * so should not call the destructor on it. */ e2x = valueNoDtor(e2x); } in `ExpressionSemanticVisitor.visit(AssignExp exp)` in the file `expressionsem.d` (currently on line 7874) is where we should modify things. I'm not sure if it suffices to just do e2x = valueNoDtor(e2x); for the case where `ex2` (`a` in the code example) is the final reference (which I also need to figure out how to do detect). I'm guessing not because `e2x` (variable `a` in the code above) is not an r-value expression. More specifically it would be nice to have a brief explanation of the meaning of Expression e = e1x.copy(); // TODO is this needed in the move case? e.type = e.type.mutableOf(); TODO I guess we should keep as is, right? if (e.type.isShared && !sd.type.isShared) e.type = e.type.unSharedOf(); // TODO I guess we should keep as is, right? e = new BlitExp(exp.loc, e, e2x); // TODO I guess we need this for raw data move, right? e = new DotVarExp(exp.loc, e, sd.postblit, false); // I guess we don't this, right? e = new CallExp(exp.loc, e); // TODO do we need this? result = e.expressionSemantic(sc); // TODO I guess we should keep as is, right? and in what way they should be modified for the move case. I'm presume we need the `BlitExp` for raw data copying from rhs and lhs and to disable the destructor for `e2x` (rhs). This leads up to two things I need help with: 1. Given that I do figure out a way to detect when an expression is the final reference to an l-value how do I update the AST so that `e2` is moved to `e1` without calling `e1`'s postblit? 2. I also warmly welcome tips on how to detect when a ref to an l-value _is_ the last ref in the scope of that l-value's lifetime. I tried posting this on dmd-internals list after having registered my email per.nordlow gmail.com but that errors as ``` SMTP error: Error (Unexpected MAIL FROM response) while handling line from SMTP server: 451 4.7.1 Please try again later (TEMPFAIL) ``` . Solution will be added to https://github.com/dlang/dmd/pull/8866.
Oct 26 2018