Skip to content

Commit 8e235d7

Browse files
authored
Merge pull request #60404 from gottesmm/pr-4dfd8089258ab2b78ff84b6ac4f4c425b321653d
[move-keyword] Change from using a move function -> move keyword.
2 parents b8c61e1 + e9d8f36 commit 8e235d7

25 files changed

+462
-376
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6428,6 +6428,8 @@ ERROR(concurrency_task_to_thread_model_global_actor_annotation,none,
64286428

64296429
ERROR(moveOnly_not_allowed_here,none,
64306430
"'moveOnly' may only be applied to classes, structs, and enums", ())
6431+
ERROR(move_expression_not_passed_lvalue,none,
6432+
"'move' can only be applied to lvalues", ())
64316433

64326434
#define UNDEFINE_DIAGNOSTIC_MACROS
64336435
#include "DefineDiagnosticMacros.h"

include/swift/AST/Expr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,33 @@ class AwaitExpr final : public IdentityExpr {
21062106
}
21072107
};
21082108

2109+
/// MoveExpr - A 'move' surrounding an lvalue expression marking the lvalue as
2110+
/// needing to be moved.
2111+
///
2112+
/// getSemanticsProvidingExpr() looks through this because it doesn't
2113+
/// provide the value and only very specific clients care where the
2114+
/// 'move' was written.
2115+
class MoveExpr final : public IdentityExpr {
2116+
SourceLoc MoveLoc;
2117+
2118+
public:
2119+
MoveExpr(SourceLoc moveLoc, Expr *sub, Type type = Type(),
2120+
bool implicit = false)
2121+
: IdentityExpr(ExprKind::Move, sub, type, implicit), MoveLoc(moveLoc) {}
2122+
2123+
static MoveExpr *createImplicit(ASTContext &ctx, SourceLoc moveLoc, Expr *sub,
2124+
Type type = Type()) {
2125+
return new (ctx) MoveExpr(moveLoc, sub, type, /*implicit=*/true);
2126+
}
2127+
2128+
SourceLoc getLoc() const { return MoveLoc; }
2129+
2130+
SourceLoc getStartLoc() const { return MoveLoc; }
2131+
SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }
2132+
2133+
static bool classof(const Expr *e) { return e->getKind() == ExprKind::Move; }
2134+
};
2135+
21092136
/// TupleExpr - Parenthesized expressions like '(a: x+x)' and '(x, y, 4)'. Note
21102137
/// that expressions like '(4)' are represented with a ParenExpr.
21112138
class TupleExpr final : public Expr,

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ ABSTRACT_EXPR(Identity, Expr)
107107
EXPR(Paren, IdentityExpr)
108108
EXPR(DotSelf, IdentityExpr)
109109
EXPR(Await, IdentityExpr)
110+
EXPR(Move, IdentityExpr)
110111
EXPR(UnresolvedMemberChainResult, IdentityExpr)
111112
EXPR_RANGE(Identity, Paren, UnresolvedMemberChainResult)
112113
ABSTRACT_EXPR(AnyTry, Expr)

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
20762076
printRec(E->getSubExpr());
20772077
PrintWithColorRAII(OS, ParenthesisColor) << ')';
20782078
}
2079+
void visitMoveExpr(MoveExpr *E) {
2080+
printCommon(E, "move_expr");
2081+
OS << '\n';
2082+
printRec(E->getSubExpr());
2083+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2084+
}
20792085
void visitUnresolvedMemberChainResultExpr(UnresolvedMemberChainResultExpr *E){
20802086
printCommon(E, "unresolved_member_chain_expr");
20812087
OS << '\n';

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4526,6 +4526,11 @@ void PrintAST::visitAwaitExpr(AwaitExpr *expr) {
45264526
visit(expr->getSubExpr());
45274527
}
45284528

4529+
void PrintAST::visitMoveExpr(MoveExpr *expr) {
4530+
Printer << "move ";
4531+
visit(expr->getSubExpr());
4532+
}
4533+
45294534
void PrintAST::visitInOutExpr(InOutExpr *expr) {
45304535
visit(expr->getSubExpr());
45314536
}

lib/AST/Expr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
365365
PASS_THROUGH_REFERENCE(UnresolvedMemberChainResult, getSubExpr);
366366
PASS_THROUGH_REFERENCE(DotSelf, getSubExpr);
367367
PASS_THROUGH_REFERENCE(Await, getSubExpr);
368+
PASS_THROUGH_REFERENCE(Move, getSubExpr);
368369
PASS_THROUGH_REFERENCE(Try, getSubExpr);
369370
PASS_THROUGH_REFERENCE(ForceTry, getSubExpr);
370371
PASS_THROUGH_REFERENCE(OptionalTry, getSubExpr);
@@ -703,6 +704,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
703704
return true;
704705

705706
case ExprKind::Await:
707+
case ExprKind::Move:
706708
case ExprKind::Try:
707709
case ExprKind::ForceTry:
708710
case ExprKind::OptionalTry:
@@ -881,6 +883,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
881883
case ExprKind::Sequence:
882884
case ExprKind::Paren:
883885
case ExprKind::Await:
886+
case ExprKind::Move:
884887
case ExprKind::UnresolvedMemberChainResult:
885888
case ExprKind::Try:
886889
case ExprKind::ForceTry:

lib/Parse/ParseExpr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
393393
/// 'try' expr-sequence-element(Mode)
394394
/// 'try' '?' expr-sequence-element(Mode)
395395
/// 'try' '!' expr-sequence-element(Mode)
396+
/// '_move' expr-sequence-element(Mode)
396397
/// expr-unary(Mode)
397398
///
398399
/// 'try' is not actually allowed at an arbitrary position of a
@@ -432,6 +433,19 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
432433
return sub;
433434
}
434435

436+
if (Tok.isContextualKeyword("_move")) {
437+
Tok.setKind(tok::contextual_keyword);
438+
SourceLoc awaitLoc = consumeToken();
439+
ParserResult<Expr> sub =
440+
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
441+
if (!sub.hasCodeCompletion() && !sub.isNull()) {
442+
ElementContext.setCreateSyntax(SyntaxKind::MoveExpr);
443+
sub = makeParserResult(new (Context) MoveExpr(awaitLoc, sub.get()));
444+
}
445+
446+
return sub;
447+
}
448+
435449
SourceLoc tryLoc;
436450
bool hadTry = consumeIf(tok::kw_try, tryLoc);
437451
Optional<Token> trySuffix;

lib/SILGen/SILGenExpr.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "LValue.h"
2020
#include "RValue.h"
2121
#include "ResultPlan.h"
22+
#include "SGFContext.h"
2223
#include "SILGen.h"
2324
#include "SILGenDynamicCast.h"
2425
#include "SILGenFunctionBuilder.h"
@@ -42,6 +43,7 @@
4243
#include "swift/Basic/type_traits.h"
4344
#include "swift/SIL/DynamicCasts.h"
4445
#include "swift/SIL/SILArgument.h"
46+
#include "swift/SIL/SILInstruction.h"
4547
#include "swift/SIL/SILUndef.h"
4648
#include "swift/SIL/TypeLowering.h"
4749
#include "llvm/ADT/STLExtras.h"
@@ -537,6 +539,7 @@ namespace {
537539
LinearFunctionExtractOriginalExpr *E, SGFContext C);
538540
RValue visitLinearToDifferentiableFunctionExpr(
539541
LinearToDifferentiableFunctionExpr *E, SGFContext C);
542+
RValue visitMoveExpr(MoveExpr *E, SGFContext C);
540543
};
541544
} // end anonymous namespace
542545

@@ -5848,6 +5851,39 @@ RValue RValueEmitter::visitErrorExpr(ErrorExpr *E, SGFContext C) {
58485851
llvm::report_fatal_error("Found an ErrorExpr but didn't emit an error?");
58495852
}
58505853

5854+
RValue RValueEmitter::visitMoveExpr(MoveExpr *E, SGFContext C) {
5855+
auto *subExpr = cast<DeclRefExpr>(E->getSubExpr());
5856+
auto subASTType = subExpr->getType()->getCanonicalType();
5857+
5858+
auto subType = SGF.getLoweredType(subASTType);
5859+
5860+
if (subType.isLoadable(SGF.F)) {
5861+
auto mv = SGF.emitRValue(subExpr).getAsSingleValue(SGF, subExpr);
5862+
if (mv.getType().isTrivial(SGF.F))
5863+
return RValue(SGF, {mv}, subType.getASTType());
5864+
mv = SGF.B.createMoveValue(E, mv);
5865+
auto *movedValue = cast<MoveValueInst>(mv.getValue());
5866+
movedValue->setAllowsDiagnostics(true /*set allows diagnostics*/);
5867+
return RValue(SGF, {mv}, subType.getASTType());
5868+
}
5869+
5870+
// If we aren't loadable, then create a temporary initialization and
5871+
// mark_unresolved_move into that.
5872+
std::unique_ptr<TemporaryInitialization> optTemp;
5873+
optTemp = SGF.emitTemporary(E, SGF.getTypeLowering(subType));
5874+
SILValue toAddr = optTemp->getAddressForInPlaceInitialization(SGF, E);
5875+
assert(!isa<LValueType>(E->getType()->getCanonicalType()) &&
5876+
"Shouldn't see an lvalue type here");
5877+
5878+
ManagedValue mv =
5879+
SGF.emitRValue(subExpr, SGFContext(SGFContext::AllowImmediatePlusZero))
5880+
.getAsSingleValue(SGF, subExpr);
5881+
assert(mv.getType().isAddress());
5882+
SGF.B.createMarkUnresolvedMoveAddr(subExpr, mv.getValue(), toAddr);
5883+
optTemp->finishInitialization(SGF);
5884+
return RValue(SGF, {optTemp->getManagedAddress()}, subType.getASTType());
5885+
}
5886+
58515887
RValue SILGenFunction::emitRValue(Expr *E, SGFContext C) {
58525888
assert(!E->getType()->hasLValueType() &&
58535889
"l-values must be emitted with emitLValue");

lib/SILGen/SILGenLValue.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "LValue.h"
2424
#include "RValue.h"
2525
#include "SILGen.h"
26+
#include "SILGenFunction.h"
2627
#include "Scope.h"
2728
#include "swift/AST/DiagnosticsCommon.h"
2829
#include "swift/AST/DiagnosticsSIL.h"
@@ -35,6 +36,7 @@
3536
#include "swift/SIL/SILArgument.h"
3637
#include "swift/SIL/SILUndef.h"
3738
#include "swift/SIL/TypeLowering.h"
39+
#include "llvm/ADT/STLExtras.h"
3840
#include "llvm/Support/raw_ostream.h"
3941
using namespace swift;
4042
using namespace Lowering;
@@ -323,6 +325,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenLValue
323325
LValue visitKeyPathApplicationExpr(KeyPathApplicationExpr *e,
324326
SGFAccessKind accessKind,
325327
LValueOptions options);
328+
LValue visitMoveExpr(MoveExpr *e, SGFAccessKind accessKind,
329+
LValueOptions options);
326330

327331
// Expressions that wrap lvalues
328332

@@ -3709,6 +3713,27 @@ LValue SILGenLValue::visitInOutExpr(InOutExpr *e, SGFAccessKind accessKind,
37093713
return visitRec(e->getSubExpr(), accessKind, options);
37103714
}
37113715

3716+
LValue SILGenLValue::visitMoveExpr(MoveExpr *e, SGFAccessKind accessKind,
3717+
LValueOptions options) {
3718+
// Do formal evaluation of the base l-value.
3719+
LValue baseLV = visitRec(e->getSubExpr(), SGFAccessKind::ReadWrite,
3720+
options.forComputedBaseLValue());
3721+
3722+
ManagedValue addr = SGF.emitAddressOfLValue(e, std::move(baseLV));
3723+
3724+
// Now create the temporary and
3725+
auto temp =
3726+
SGF.emitFormalAccessTemporary(e, SGF.F.getTypeLowering(addr.getType()));
3727+
auto toAddr = temp->getAddressForInPlaceInitialization(SGF, e);
3728+
SGF.B.createMarkUnresolvedMoveAddr(e, addr.getValue(), toAddr);
3729+
temp->finishInitialization(SGF);
3730+
3731+
// Now return the temporary in a value component.
3732+
return LValue::forValue(SGFAccessKind::BorrowedAddressRead,
3733+
temp->getManagedAddress(),
3734+
toAddr->getType().getASTType());
3735+
}
3736+
37123737
/// Emit an lvalue that refers to the given property. This is
37133738
/// designed to work with ManagedValue 'base's that are either +0 or +1.
37143739
LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base,

lib/Sema/MiscDiagnostics.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
#include "TypeCheckConcurrency.h"
2020
#include "TypeChecker.h"
2121
#include "swift/AST/ASTWalker.h"
22+
#include "swift/AST/DiagnosticsSema.h"
2223
#include "swift/AST/ExistentialLayout.h"
24+
#include "swift/AST/Expr.h"
2325
#include "swift/AST/NameLookup.h"
2426
#include "swift/AST/NameLookupRequests.h"
2527
#include "swift/AST/Pattern.h"
2628
#include "swift/AST/SourceFile.h"
2729
#include "swift/AST/Stmt.h"
2830
#include "swift/AST/TypeCheckRequests.h"
31+
#include "swift/AST/Types.h"
2932
#include "swift/Basic/Defer.h"
3033
#include "swift/Basic/SourceManager.h"
3134
#include "swift/Basic/Statistic.h"
@@ -97,6 +100,7 @@ bool BaseDiagnosticWalker::shouldWalkIntoDeclInClosureContext(Decl *D) {
97100
/// invalid positions.
98101
/// - Marker protocols cannot occur as the type of an as? or is expression.
99102
/// - KeyPath expressions cannot refer to effectful properties / subscripts
103+
/// - Move expressions must have a declref expr subvalue.
100104
///
101105
static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
102106
bool isExprStmt) {
@@ -317,7 +321,13 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
317321
if (auto cast = dyn_cast<CheckedCastExpr>(E)) {
318322
checkCheckedCastExpr(cast);
319323
}
320-
324+
325+
// Diagnose move expression uses where the sub expression is not a declref
326+
// expr.
327+
if (auto *moveExpr = dyn_cast<MoveExpr>(E)) {
328+
checkMoveExpr(moveExpr);
329+
}
330+
321331
return { true, E };
322332
}
323333

@@ -357,6 +367,13 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
357367
}
358368
}
359369

370+
void checkMoveExpr(MoveExpr *moveExpr) {
371+
if (!isa<DeclRefExpr>(moveExpr->getSubExpr())) {
372+
Ctx.Diags.diagnose(moveExpr->getLoc(),
373+
diag::move_expression_not_passed_lvalue);
374+
}
375+
}
376+
360377
static Expr *lookThroughArgument(Expr *arg) {
361378
while (1) {
362379
if (auto conv = dyn_cast<ImplicitConversionExpr>(arg))

stdlib/public/core/LifetimeManager.swift

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -166,35 +166,6 @@ extension String {
166166
}
167167
}
168168

169-
/// Takes in a value at +1 and performs a Builtin.move upon it.
170-
///
171-
/// IMPLEMENTATION NOTES: During transparent inlining, Builtin.move becomes the
172-
/// move_value instruction if we are inlining into a context where the
173-
/// specialized type is loadable. If the transparent function is called in a
174-
/// context where the inlined function specializes such that the specialized
175-
/// type is still not loadable, the compiler aborts (a). Once we have opaque
176-
/// values, this restriction will be lifted since after that address only types
177-
/// at SILGen time will be loadable objects.
178-
///
179-
/// (a). This is implemented by requiring that Builtin.move only be called
180-
/// within a function marked with the semantic tag "lifetimemanagement.move"
181-
/// which conveniently is only the function we are defining here: _move.
182-
///
183-
/// NOTE: We mark this _alwaysEmitIntoClient to ensure that we are not creating
184-
/// new ABI that the stdlib must maintain if a user calls this ignoring the '_'
185-
/// implying it is stdlib SPI.
186-
@_alwaysEmitIntoClient
187-
@inlinable
188-
@_transparent
189-
@_semantics("lifetimemanagement.move")
190-
public func _move<T>(_ value: __owned T) -> T {
191-
#if $BuiltinMove
192-
Builtin.move(value)
193-
#else
194-
value
195-
#endif
196-
}
197-
198169
/// Takes in a value at +0 and performs a Builtin.copy upon it.
199170
///
200171
/// IMPLEMENTATION NOTES: During transparent inlining, Builtin.copy becomes the

0 commit comments

Comments
 (0)