Skip to content

Commit c4e8f67

Browse files
authored
Merge pull request #66032 from gottesmm/release-5.9-copy-consume
[5.9][copy-operator][consume-operator] Implement the copy operator and add some fixes for consume informed by that implementation
2 parents 82b3e75 + 91c4636 commit c4e8f67

26 files changed

+1139
-51
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,8 @@ ERROR(expected_expr_after_await, none,
13851385
"expected expression after 'await'", ())
13861386
ERROR(expected_expr_after_move, none,
13871387
"expected expression after 'consume'", ())
1388+
ERROR(expected_expr_after_copy, none,
1389+
"expected expression after 'copy'", ())
13881390
ERROR(expected_expr_after_borrow, none,
13891391
"expected expression after '_borrow'", ())
13901392

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6990,10 +6990,14 @@ ERROR(concurrency_task_to_thread_model_global_actor_annotation,none,
69906990

69916991
ERROR(moveOnly_not_allowed_here,none,
69926992
"'moveOnly' only applies to structs or enums", ())
6993-
ERROR(move_expression_not_passed_lvalue,none,
6993+
ERROR(consume_expression_not_passed_lvalue,none,
69946994
"'consume' can only be applied to lvalues", ())
69956995
ERROR(borrow_expression_not_passed_lvalue,none,
69966996
"'borrow' can only be applied to lvalues", ())
6997+
ERROR(copy_expression_not_passed_lvalue,none,
6998+
"'copy' can only be applied to lvalues", ())
6999+
ERROR(copy_expression_cannot_be_used_with_noncopyable_types,none,
7000+
"'copy' cannot be applied to noncopyable types", ())
69977001

69987002
ERROR(moveOnly_requires_lexical_lifetimes,none,
69997003
"noncopyable types require lexical borrow scopes "

include/swift/AST/Expr.h

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,31 +2050,61 @@ class AwaitExpr final : public IdentityExpr {
20502050
}
20512051
};
20522052

2053-
/// MoveExpr - A 'move' surrounding an lvalue expression marking the lvalue as
2054-
/// needing to be moved.
2055-
///
2056-
/// getSemanticsProvidingExpr() looks through this because it doesn't
2057-
/// provide the value and only very specific clients care where the
2058-
/// 'move' was written.
2059-
class MoveExpr final : public IdentityExpr {
2060-
SourceLoc MoveLoc;
2053+
/// ConsumeExpr - A 'consume' surrounding an lvalue expression marking the
2054+
/// lvalue as needing to be moved.
2055+
class ConsumeExpr final : public Expr {
2056+
Expr *SubExpr;
2057+
SourceLoc ConsumeLoc;
20612058

20622059
public:
2063-
MoveExpr(SourceLoc moveLoc, Expr *sub, Type type = Type(),
2060+
ConsumeExpr(SourceLoc consumeLoc, Expr *sub, Type type = Type(),
2061+
bool implicit = false)
2062+
: Expr(ExprKind::Consume, implicit, type), SubExpr(sub),
2063+
ConsumeLoc(consumeLoc) {}
2064+
2065+
static ConsumeExpr *createImplicit(ASTContext &ctx, SourceLoc moveLoc,
2066+
Expr *sub, Type type = Type()) {
2067+
return new (ctx) ConsumeExpr(moveLoc, sub, type, /*implicit=*/true);
2068+
}
2069+
2070+
SourceLoc getLoc() const { return ConsumeLoc; }
2071+
2072+
Expr *getSubExpr() const { return SubExpr; }
2073+
void setSubExpr(Expr *E) { SubExpr = E; }
2074+
2075+
SourceLoc getStartLoc() const { return getLoc(); }
2076+
SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }
2077+
2078+
static bool classof(const Expr *e) {
2079+
return e->getKind() == ExprKind::Consume;
2080+
}
2081+
};
2082+
2083+
/// CopyExpr - A 'copy' surrounding an lvalue expression marking the lvalue as
2084+
/// needing a semantic copy. Used to force a copy of a no implicit copy type.
2085+
class CopyExpr final : public Expr {
2086+
Expr *SubExpr;
2087+
SourceLoc CopyLoc;
2088+
2089+
public:
2090+
CopyExpr(SourceLoc copyLoc, Expr *sub, Type type = Type(),
20642091
bool implicit = false)
2065-
: IdentityExpr(ExprKind::Move, sub, type, implicit), MoveLoc(moveLoc) {}
2092+
: Expr(ExprKind::Copy, implicit, type), SubExpr(sub), CopyLoc(copyLoc) {}
20662093

2067-
static MoveExpr *createImplicit(ASTContext &ctx, SourceLoc moveLoc, Expr *sub,
2094+
static CopyExpr *createImplicit(ASTContext &ctx, SourceLoc copyLoc, Expr *sub,
20682095
Type type = Type()) {
2069-
return new (ctx) MoveExpr(moveLoc, sub, type, /*implicit=*/true);
2096+
return new (ctx) CopyExpr(copyLoc, sub, type, /*implicit=*/true);
20702097
}
20712098

2072-
SourceLoc getLoc() const { return MoveLoc; }
2099+
SourceLoc getLoc() const { return CopyLoc; }
2100+
2101+
Expr *getSubExpr() const { return SubExpr; }
2102+
void setSubExpr(Expr *E) { SubExpr = E; }
20732103

2074-
SourceLoc getStartLoc() const { return MoveLoc; }
2104+
SourceLoc getStartLoc() const { return CopyLoc; }
20752105
SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }
20762106

2077-
static bool classof(const Expr *e) { return e->getKind() == ExprKind::Move; }
2107+
static bool classof(const Expr *e) { return e->getKind() == ExprKind::Copy; }
20782108
};
20792109

20802110
/// BorrowExpr - A 'borrow' surrounding an lvalue/accessor expression at an

include/swift/AST/ExprNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,11 @@ ABSTRACT_EXPR(Identity, Expr)
107107
EXPR(Paren, IdentityExpr)
108108
EXPR(DotSelf, IdentityExpr)
109109
EXPR(Await, IdentityExpr)
110-
EXPR(Move, IdentityExpr)
111110
EXPR(Borrow, IdentityExpr)
112111
EXPR(UnresolvedMemberChainResult, IdentityExpr)
113112
EXPR_RANGE(Identity, Paren, UnresolvedMemberChainResult)
113+
EXPR(Copy, Expr)
114+
EXPR(Consume, Expr)
114115
ABSTRACT_EXPR(AnyTry, Expr)
115116
EXPR(Try, AnyTryExpr)
116117
EXPR(ForceTry, AnyTryExpr)

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,8 +2194,14 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21942194
printRec(E->getSubExpr());
21952195
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21962196
}
2197-
void visitMoveExpr(MoveExpr *E) {
2198-
printCommon(E, "move_expr");
2197+
void visitConsumeExpr(ConsumeExpr *E) {
2198+
printCommon(E, "consume_expr");
2199+
OS << '\n';
2200+
printRec(E->getSubExpr());
2201+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2202+
}
2203+
void visitCopyExpr(CopyExpr *E) {
2204+
printCommon(E, "copy_expr");
21992205
OS << '\n';
22002206
printRec(E->getSubExpr());
22012207
PrintWithColorRAII(OS, ParenthesisColor) << ')';

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4979,8 +4979,13 @@ void PrintAST::visitAwaitExpr(AwaitExpr *expr) {
49794979
visit(expr->getSubExpr());
49804980
}
49814981

4982-
void PrintAST::visitMoveExpr(MoveExpr *expr) {
4983-
Printer << "move ";
4982+
void PrintAST::visitConsumeExpr(ConsumeExpr *expr) {
4983+
Printer << "consume ";
4984+
visit(expr->getSubExpr());
4985+
}
4986+
4987+
void PrintAST::visitCopyExpr(CopyExpr *expr) {
4988+
Printer << "copy ";
49844989
visit(expr->getSubExpr());
49854990
}
49864991

lib/AST/ASTWalker.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,23 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
690690
}
691691
return nullptr;
692692
}
693+
694+
Expr *visitCopyExpr(CopyExpr *E) {
695+
if (Expr *subExpr = doIt(E->getSubExpr())) {
696+
E->setSubExpr(subExpr);
697+
return E;
698+
}
699+
return nullptr;
700+
}
701+
702+
Expr *visitConsumeExpr(ConsumeExpr *E) {
703+
if (Expr *subExpr = doIt(E->getSubExpr())) {
704+
E->setSubExpr(subExpr);
705+
return E;
706+
}
707+
return nullptr;
708+
}
709+
693710
Expr *visitTupleExpr(TupleExpr *E) {
694711
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i)
695712
if (E->getElement(i)) {

lib/AST/Expr.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ SourceLoc Expr::getLoc() const {
192192
Expr *Expr::getSemanticsProvidingExpr() {
193193
if (auto *IE = dyn_cast<IdentityExpr>(this))
194194
return IE->getSubExpr()->getSemanticsProvidingExpr();
195-
196195
if (auto *TE = dyn_cast<TryExpr>(this))
197196
return TE->getSubExpr()->getSemanticsProvidingExpr();
198197

@@ -371,7 +370,8 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
371370
PASS_THROUGH_REFERENCE(UnresolvedMemberChainResult, getSubExpr);
372371
PASS_THROUGH_REFERENCE(DotSelf, getSubExpr);
373372
PASS_THROUGH_REFERENCE(Await, getSubExpr);
374-
PASS_THROUGH_REFERENCE(Move, getSubExpr);
373+
PASS_THROUGH_REFERENCE(Consume, getSubExpr);
374+
PASS_THROUGH_REFERENCE(Copy, getSubExpr);
375375
PASS_THROUGH_REFERENCE(Borrow, getSubExpr);
376376
PASS_THROUGH_REFERENCE(Try, getSubExpr);
377377
PASS_THROUGH_REFERENCE(ForceTry, getSubExpr);
@@ -743,7 +743,8 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
743743
return true;
744744

745745
case ExprKind::Await:
746-
case ExprKind::Move:
746+
case ExprKind::Consume:
747+
case ExprKind::Copy:
747748
case ExprKind::Borrow:
748749
case ExprKind::Try:
749750
case ExprKind::ForceTry:
@@ -935,7 +936,8 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
935936
case ExprKind::Sequence:
936937
case ExprKind::Paren:
937938
case ExprKind::Await:
938-
case ExprKind::Move:
939+
case ExprKind::Consume:
940+
case ExprKind::Copy:
939941
case ExprKind::Borrow:
940942
case ExprKind::UnresolvedMemberChainResult:
941943
case ExprKind::Try:

lib/Parse/ParseExpr.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,15 +409,31 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
409409
}
410410

411411
if (Tok.isContextualKeyword("consume")
412-
&& peekToken().isAny(tok::identifier, tok::kw_self)
412+
&& peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
413+
tok::code_complete)
413414
&& !peekToken().isAtStartOfLine()) {
414415
Tok.setKind(tok::contextual_keyword);
415416

416417
SourceLoc consumeLoc = consumeToken();
417418
ParserResult<Expr> sub =
418419
parseExprSequenceElement(diag::expected_expr_after_move, isExprBasic);
419-
if (!sub.hasCodeCompletion() && !sub.isNull()) {
420-
sub = makeParserResult(new (Context) MoveExpr(consumeLoc, sub.get()));
420+
if (!sub.isNull()) {
421+
sub = makeParserResult(new (Context) ConsumeExpr(consumeLoc, sub.get()));
422+
}
423+
return sub;
424+
}
425+
426+
if (Tok.isContextualKeyword("copy") &&
427+
peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
428+
tok::code_complete) &&
429+
!peekToken().isAtStartOfLine()) {
430+
Tok.setKind(tok::contextual_keyword);
431+
432+
SourceLoc copyLoc = consumeToken();
433+
ParserResult<Expr> sub =
434+
parseExprSequenceElement(diag::expected_expr_after_copy, isExprBasic);
435+
if (!sub.isNull()) {
436+
sub = makeParserResult(new (Context) CopyExpr(copyLoc, sub.get()));
421437
}
422438
return sub;
423439
}
@@ -432,7 +448,7 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
432448
ParserResult<Expr> sub =
433449
parseExprSequenceElement(diag::expected_expr_after_move, isExprBasic);
434450
if (!sub.hasCodeCompletion() && !sub.isNull()) {
435-
sub = makeParserResult(new (Context) MoveExpr(awaitLoc, sub.get()));
451+
sub = makeParserResult(new (Context) ConsumeExpr(awaitLoc, sub.get()));
436452
}
437453
return sub;
438454
}

lib/SILGen/SILGenBuilder.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,3 +1050,9 @@ void SILGenBuilder::emitCopyAddrOperation(SILLocation loc, SILValue srcAddr,
10501050
auto &lowering = getTypeLowering(srcAddr->getType());
10511051
lowering.emitCopyInto(*this, loc, srcAddr, destAddr, isTake, isInitialize);
10521052
}
1053+
1054+
ManagedValue SILGenBuilder::createExplicitCopyValue(SILLocation loc,
1055+
ManagedValue operand) {
1056+
auto cvi = SILBuilder::createExplicitCopyValue(loc, operand.getValue());
1057+
return SGF.emitManagedRValueWithCleanup(cvi);
1058+
}

lib/SILGen/SILGenBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ class SILGenBuilder : public SILBuilder {
125125
ManagedValue createFormalAccessCopyValue(SILLocation loc,
126126
ManagedValue originalValue);
127127

128+
using SILBuilder::createExplicitCopyValue;
129+
130+
/// A copy_value operation that to the move checker looks like just a normal
131+
/// liveness use. Used to implement an explicit copy for no implicit copy
132+
/// values.
133+
ManagedValue createExplicitCopyValue(SILLocation Loc, ManagedValue operand);
134+
128135
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
129136
using SILBuilder::createStrongCopy##Name##Value; \
130137
ManagedValue createStrongCopy##Name##Value(SILLocation loc, \

0 commit comments

Comments
 (0)