Skip to content

Commit d14e9eb

Browse files
committed
[copy-operator] Add support for the copy operator in preparation for making consuming and borrowing no implicit copy.
rdar://101862423
1 parent f16bf16 commit d14e9eb

17 files changed

+878
-0
lines changed

include/swift/AST/DiagnosticsParse.def

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

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6996,6 +6996,10 @@ ERROR(move_expression_not_passed_lvalue,none,
69966996
"'consume' can only be applied to lvalues", ())
69976997
ERROR(borrow_expression_not_passed_lvalue,none,
69986998
"'borrow' can only be applied to lvalues", ())
6999+
ERROR(copy_expression_not_passed_lvalue,none,
7000+
"'copy' can only be applied to lvalues", ())
7001+
ERROR(copy_expression_cannot_be_used_with_noncopyable_types,none,
7002+
"'copy' cannot be applied to noncopyable types", ())
69997003

70007004
ERROR(moveOnly_requires_lexical_lifetimes,none,
70017005
"noncopyable types require lexical borrow scopes "

include/swift/AST/Expr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,33 @@ class MoveExpr final : public IdentityExpr {
20772077
static bool classof(const Expr *e) { return e->getKind() == ExprKind::Move; }
20782078
};
20792079

2080+
/// CopyExpr - A 'copy' surrounding an lvalue expression marking the lvalue as
2081+
/// needing a semantic copy. Used to force a copy of a no implicit copy type.
2082+
///
2083+
/// getSemanticsProvidingExpr() looks through this because it doesn't
2084+
/// provide the value and only very specific clients care where the
2085+
/// 'move' was written.
2086+
class CopyExpr final : public IdentityExpr {
2087+
SourceLoc CopyLoc;
2088+
2089+
public:
2090+
CopyExpr(SourceLoc copyLoc, Expr *sub, Type type = Type(),
2091+
bool implicit = false)
2092+
: IdentityExpr(ExprKind::Copy, sub, type, implicit), CopyLoc(copyLoc) {}
2093+
2094+
static CopyExpr *createImplicit(ASTContext &ctx, SourceLoc copyLoc, Expr *sub,
2095+
Type type = Type()) {
2096+
return new (ctx) CopyExpr(copyLoc, sub, type, /*implicit=*/true);
2097+
}
2098+
2099+
SourceLoc getLoc() const { return CopyLoc; }
2100+
2101+
SourceLoc getStartLoc() const { return CopyLoc; }
2102+
SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }
2103+
2104+
static bool classof(const Expr *e) { return e->getKind() == ExprKind::Copy; }
2105+
};
2106+
20802107
/// BorrowExpr - A 'borrow' surrounding an lvalue/accessor expression at an
20812108
/// apply site marking the lvalue/accessor as being borrowed when passed to the
20822109
/// callee.

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ ABSTRACT_EXPR(Identity, Expr)
108108
EXPR(DotSelf, IdentityExpr)
109109
EXPR(Await, IdentityExpr)
110110
EXPR(Move, IdentityExpr)
111+
EXPR(Copy, IdentityExpr)
111112
EXPR(Borrow, IdentityExpr)
112113
EXPR(UnresolvedMemberChainResult, IdentityExpr)
113114
EXPR_RANGE(Identity, Paren, UnresolvedMemberChainResult)

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
22002200
printRec(E->getSubExpr());
22012201
PrintWithColorRAII(OS, ParenthesisColor) << ')';
22022202
}
2203+
void visitCopyExpr(CopyExpr *E) {
2204+
printCommon(E, "copy_expr");
2205+
OS << '\n';
2206+
printRec(E->getSubExpr());
2207+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2208+
}
22032209
void visitBorrowExpr(BorrowExpr *E) {
22042210
printCommon(E, "borrow_expr");
22052211
OS << '\n';

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5001,6 +5001,11 @@ void PrintAST::visitMoveExpr(MoveExpr *expr) {
50015001
visit(expr->getSubExpr());
50025002
}
50035003

5004+
void PrintAST::visitCopyExpr(CopyExpr *expr) {
5005+
Printer << "copy ";
5006+
visit(expr->getSubExpr());
5007+
}
5008+
50045009
void PrintAST::visitBorrowExpr(BorrowExpr *expr) {
50055010
Printer << "borrow ";
50065011
visit(expr->getSubExpr());

lib/AST/Expr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
372372
PASS_THROUGH_REFERENCE(DotSelf, getSubExpr);
373373
PASS_THROUGH_REFERENCE(Await, getSubExpr);
374374
PASS_THROUGH_REFERENCE(Move, getSubExpr);
375+
PASS_THROUGH_REFERENCE(Copy, getSubExpr);
375376
PASS_THROUGH_REFERENCE(Borrow, getSubExpr);
376377
PASS_THROUGH_REFERENCE(Try, getSubExpr);
377378
PASS_THROUGH_REFERENCE(ForceTry, getSubExpr);
@@ -744,6 +745,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
744745

745746
case ExprKind::Await:
746747
case ExprKind::Move:
748+
case ExprKind::Copy:
747749
case ExprKind::Borrow:
748750
case ExprKind::Try:
749751
case ExprKind::ForceTry:
@@ -936,6 +938,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
936938
case ExprKind::Paren:
937939
case ExprKind::Await:
938940
case ExprKind::Move:
941+
case ExprKind::Copy:
939942
case ExprKind::Borrow:
940943
case ExprKind::UnresolvedMemberChainResult:
941944
case ExprKind::Try:

lib/Parse/ParseExpr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,21 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
422422
return sub;
423423
}
424424

425+
if (Tok.isContextualKeyword("copy") &&
426+
peekToken().isAny(tok::identifier, tok::kw_self,
427+
tok::dollarident) &&
428+
!peekToken().isAtStartOfLine()) {
429+
Tok.setKind(tok::contextual_keyword);
430+
431+
SourceLoc copyLoc = consumeToken();
432+
ParserResult<Expr> sub =
433+
parseExprSequenceElement(diag::expected_expr_after_copy, isExprBasic);
434+
if (!sub.hasCodeCompletion() && !sub.isNull()) {
435+
sub = makeParserResult(new (Context) CopyExpr(copyLoc, sub.get()));
436+
}
437+
return sub;
438+
}
439+
425440
if (Context.LangOpts.hasFeature(Feature::OldOwnershipOperatorSpellings)) {
426441
if (Tok.isContextualKeyword("_move")) {
427442
Tok.setKind(tok::contextual_keyword);

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)