[Dlang-internal] Enable more pass-by-move of structs
Per Nordlöw
per.nordlow at gmail.com
Fri Oct 26 11:56:51 UTC 2018
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 at 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.
More information about the Dlang-internal
mailing list