mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 20:50:41 +03:00
Accept __rvalue attribute on ref functions; which will force the result to be treated as __rvalue. (#20946)
This is essential to implement `move`, `forward`, etc.
This commit is contained in:
parent
c6e387c448
commit
603225372b
5 changed files with 44 additions and 5 deletions
|
@ -23,5 +23,18 @@ This also applies to constructors and assignments, meaning move constructors and
|
|||
move assignments are enabled. Moving instead of copying can be much more resource
|
||||
efficient, as, say, a string can be moved rather than copied/deleted.
|
||||
|
||||
A moved object can still be destructed, so take that into account when moving
|
||||
A moved object will still be destructed, so take that into account when moving
|
||||
a field - set it to a benign value that can be destructed.
|
||||
|
||||
`__rvalue` may also be used as an attribute on a function which returns by ref
|
||||
to declare that the result should be treated as an rvalue at the callsite:
|
||||
```
|
||||
ref T move(T)(return ref T source) __rvalue
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
S s;
|
||||
S t = move(s); // call expression rewritten as: S t = __rvalue(move(s))
|
||||
```
|
||||
This is used as an internal tool to implement library primitives such as `move` and `forward`.
|
||||
|
|
|
@ -5893,6 +5893,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
printf("CallExp::semantic() %s\n", exp.toChars());
|
||||
}
|
||||
|
||||
scope (exit)
|
||||
{
|
||||
if (TypeFunction tf = exp.f ? cast(TypeFunction)exp.f.type : null)
|
||||
{
|
||||
result.rvalue = tf.isRvalue;
|
||||
if (tf.isRvalue && !tf.isRef)
|
||||
{
|
||||
error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`");
|
||||
setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Objects* tiargs = null; // initial list of template arguments
|
||||
Expression ethis = null;
|
||||
Type tthis = null;
|
||||
|
@ -10839,7 +10852,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (sd.hasMoveCtor && !e2x.isCallExp() && !e2x.isStructLiteralExp())
|
||||
else if (sd.hasMoveCtor && (!e2x.isCallExp() || e2x.rvalue) && !e2x.isStructLiteralExp())
|
||||
{
|
||||
// #move
|
||||
/* The !e2x.isCallExp() is because it is already an rvalue
|
||||
|
|
|
@ -4596,6 +4596,7 @@ private:
|
|||
bool isInOutQual;
|
||||
bool isCtor;
|
||||
bool isReturnScope;
|
||||
bool isRvalue;
|
||||
BitFields() :
|
||||
isNothrow(),
|
||||
isNogc(),
|
||||
|
@ -4610,10 +4611,11 @@ private:
|
|||
isInOutParam(),
|
||||
isInOutQual(),
|
||||
isCtor(),
|
||||
isReturnScope()
|
||||
isReturnScope(),
|
||||
isRvalue()
|
||||
{
|
||||
}
|
||||
BitFields(bool isNothrow, bool isNogc = false, bool isProperty = false, bool isRef = false, bool isReturn = false, bool isScopeQual = false, bool isReturnInferred = false, bool isScopeInferred = false, bool isLive = false, bool incomplete = false, bool isInOutParam = false, bool isInOutQual = false, bool isCtor = false, bool isReturnScope = false) :
|
||||
BitFields(bool isNothrow, bool isNogc = false, bool isProperty = false, bool isRef = false, bool isReturn = false, bool isScopeQual = false, bool isReturnInferred = false, bool isScopeInferred = false, bool isLive = false, bool incomplete = false, bool isInOutParam = false, bool isInOutQual = false, bool isCtor = false, bool isReturnScope = false, bool isRvalue = false) :
|
||||
isNothrow(isNothrow),
|
||||
isNogc(isNogc),
|
||||
isProperty(isProperty),
|
||||
|
@ -4627,7 +4629,8 @@ private:
|
|||
isInOutParam(isInOutParam),
|
||||
isInOutQual(isInOutQual),
|
||||
isCtor(isCtor),
|
||||
isReturnScope(isReturnScope)
|
||||
isReturnScope(isReturnScope),
|
||||
isRvalue(isRvalue)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -4660,6 +4663,8 @@ public:
|
|||
bool isCtor(bool v);
|
||||
bool isReturnScope() const;
|
||||
bool isReturnScope(bool v);
|
||||
bool isRvalue() const;
|
||||
bool isRvalue(bool v);
|
||||
private:
|
||||
uint16_t bitFields;
|
||||
public:
|
||||
|
|
|
@ -2488,6 +2488,7 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
bool isInOutQual; /// inout on the qualifier
|
||||
bool isCtor; /// the function is a constructor
|
||||
bool isReturnScope; /// `this` is returned by value
|
||||
bool isRvalue; /// returned reference should be treated as rvalue
|
||||
}
|
||||
|
||||
import dmd.common.bitfields : generateBitFields;
|
||||
|
@ -2531,6 +2532,8 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
this.isScopeQual = true;
|
||||
if (stc & STC.scopeinferred)
|
||||
this.isScopeInferred = true;
|
||||
if (stc & STC.rvalue)
|
||||
this.isRvalue = true;
|
||||
|
||||
this.trust = TRUST.default_;
|
||||
if (stc & STC.safe)
|
||||
|
@ -2567,6 +2570,7 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
t.isScopeQual = isScopeQual;
|
||||
t.isReturnInferred = isReturnInferred;
|
||||
t.isScopeInferred = isScopeInferred;
|
||||
t.isRvalue = isRvalue;
|
||||
t.isInOutParam = isInOutParam;
|
||||
t.isInOutQual = isInOutQual;
|
||||
t.trust = trust;
|
||||
|
|
|
@ -1422,6 +1422,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
stc = STC.scope_;
|
||||
break;
|
||||
|
||||
case TOK.rvalue:
|
||||
stc = STC.rvalue;
|
||||
break;
|
||||
|
||||
case TOK.at:
|
||||
{
|
||||
AST.Expressions* udas = null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue