Skip to content

Commit 27c08b1

Browse files
authored
Merge pull request swiftlang#71123 from hamishknight/sema-expr-return
Move the single-expr return transform from Parse to Sema
2 parents a9bf9f6 + ce43f0d commit 27c08b1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+346
-416
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,6 @@ class AnyFunctionRef {
9494
return !TheFunction.get<AbstractClosureExpr *>()->getType().isNull();
9595
}
9696

97-
bool hasSingleExpressionBody() const {
98-
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
99-
return AFD->hasSingleExpressionBody();
100-
return TheFunction.get<AbstractClosureExpr *>()->hasSingleExpressionBody();
101-
}
102-
103-
Expr *getSingleExpressionBody() const {
104-
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
105-
return AFD->getSingleExpressionBody();
106-
return TheFunction.get<AbstractClosureExpr *>()->getSingleExpressionBody();
107-
}
108-
10997
ParameterList *getParameters() const {
11098
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
11199
return AFD->getParameters();
@@ -152,33 +140,31 @@ class AnyFunctionRef {
152140
return cast<AutoClosureExpr>(ACE)->getBody();
153141
}
154142

155-
void setParsedBody(BraceStmt *stmt, bool isSingleExpression) {
143+
void setParsedBody(BraceStmt *stmt) {
156144
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
157145
AFD->setBody(stmt, AbstractFunctionDecl::BodyKind::Parsed);
158-
AFD->setHasSingleExpressionBody(isSingleExpression);
159146
return;
160147
}
161148

162149
auto *ACE = TheFunction.get<AbstractClosureExpr *>();
163150
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
164-
CE->setBody(stmt, isSingleExpression);
151+
CE->setBody(stmt);
165152
CE->setBodyState(ClosureExpr::BodyState::ReadyForTypeChecking);
166153
return;
167154
}
168155

169156
llvm_unreachable("autoclosures don't have statement bodies");
170157
}
171158

172-
void setTypecheckedBody(BraceStmt *stmt, bool isSingleExpression) {
159+
void setTypecheckedBody(BraceStmt *stmt) {
173160
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
174161
AFD->setBody(stmt, AbstractFunctionDecl::BodyKind::TypeChecked);
175-
AFD->setHasSingleExpressionBody(isSingleExpression);
176162
return;
177163
}
178164

179165
auto *ACE = TheFunction.get<AbstractClosureExpr *>();
180166
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
181-
CE->setBody(stmt, isSingleExpression);
167+
CE->setBody(stmt);
182168
CE->setBodyState(ClosureExpr::BodyState::TypeCheckedWithSignature);
183169
return;
184170
}

include/swift/AST/Decl.h

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
464464
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
465465
StaticSpelling : 2
466466
);
467-
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+2+2+8+1+1+1+1+1+1+1,
467+
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+2+2+8+1+1+1+1+1+1,
468468
/// \see AbstractFunctionDecl::BodyKind
469469
BodyKind : 3,
470470

@@ -492,9 +492,6 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
492492
/// Whether the function body throws.
493493
Throws : 1,
494494

495-
/// Whether this member's body consists of a single expression.
496-
HasSingleExpressionBody : 1,
497-
498495
/// Whether peeking into this function detected nested type declarations.
499496
/// This is set when skipping over the decl at parsing.
500497
HasNestedTypeDeclarations : 1,
@@ -7177,7 +7174,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
71777174
Bits.AbstractFunctionDecl.Overridden = false;
71787175
Bits.AbstractFunctionDecl.Async = Async;
71797176
Bits.AbstractFunctionDecl.Throws = Throws;
7180-
Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
71817177
Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = false;
71827178
Bits.AbstractFunctionDecl.DistributedThunk = false;
71837179
}
@@ -7211,17 +7207,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
72117207
}
72127208

72137209
public:
7214-
void setHasSingleExpressionBody(bool Has = true) {
7215-
Bits.AbstractFunctionDecl.HasSingleExpressionBody = Has;
7216-
}
7217-
7218-
bool hasSingleExpressionBody() const {
7219-
return Bits.AbstractFunctionDecl.HasSingleExpressionBody;
7220-
}
7221-
7222-
Expr *getSingleExpressionBody() const;
7223-
void setSingleExpressionBody(Expr *NewBody);
7224-
72257210
/// Returns the string for the base name, or "_" if this is unnamed.
72267211
StringRef getNameStr() const {
72277212
assert(!getName().isSpecial() && "Cannot get string for special names");

include/swift/AST/Expr.h

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3591,6 +3591,22 @@ class ArchetypeToSuperExpr : public ImplicitConversionExpr {
35913591
}
35923592
};
35933593

3594+
/// An expression that models an implicit conversion from an uninhabited value
3595+
/// to any type. It cannot be evaluated.
3596+
class UnreachableExpr : public ImplicitConversionExpr {
3597+
UnreachableExpr(Expr *subExpr, Type ty)
3598+
: ImplicitConversionExpr(ExprKind::Unreachable, subExpr, ty) {}
3599+
3600+
public:
3601+
static UnreachableExpr *create(ASTContext &ctx, Expr *subExpr, Type ty) {
3602+
return new (ctx) UnreachableExpr(subExpr, ty);
3603+
}
3604+
3605+
static bool classof(const Expr *E) {
3606+
return E->getKind() == ExprKind::Unreachable;
3607+
}
3608+
};
3609+
35943610
/// The builtin unary '&' operator, which converts the
35953611
/// given lvalue into an 'inout' argument value.
35963612
class InOutExpr : public Expr {
@@ -3927,9 +3943,7 @@ class AbstractClosureExpr : public DeclContext, public Expr {
39273943
bool hasSingleExpressionBody() const;
39283944

39293945
/// Retrieve the body for closure that has a single expression for
3930-
/// its body.
3931-
///
3932-
/// Only valid when \c hasSingleExpressionBody() is true.
3946+
/// its body, or \c nullptr if there is no single expression body.
39333947
Expr *getSingleExpressionBody() const;
39343948

39353949
/// Returns the body of closures that have a body
@@ -4055,9 +4069,9 @@ class ClosureExpr : public AbstractClosureExpr {
40554069
/// The explicitly-specified result type.
40564070
llvm::PointerIntPair<TypeExpr *, 2, BodyState> ExplicitResultTypeAndBodyState;
40574071

4058-
/// The body of the closure, along with a bit indicating whether it
4059-
/// was originally just a single expression.
4060-
llvm::PointerIntPair<BraceStmt *, 1, bool> Body;
4072+
/// The body of the closure.
4073+
BraceStmt *Body;
4074+
40614075
public:
40624076
ClosureExpr(const DeclAttributes &attributes,
40634077
SourceRange bracketRange, VarDecl *capturedSelfDecl,
@@ -4083,11 +4097,8 @@ class ClosureExpr : public AbstractClosureExpr {
40834097
SourceLoc getEndLoc() const;
40844098
SourceLoc getLoc() const;
40854099

4086-
BraceStmt *getBody() const { return Body.getPointer(); }
4087-
void setBody(BraceStmt *S, bool isSingleExpression) {
4088-
Body.setPointer(S);
4089-
Body.setInt(isSingleExpression);
4090-
}
4100+
BraceStmt *getBody() const { return Body; }
4101+
void setBody(BraceStmt *S) { Body = S; }
40914102

40924103
DeclAttributes &getAttrs() { return Attributes; }
40934104
const DeclAttributes &getAttrs() const { return Attributes; }
@@ -4202,13 +4213,11 @@ class ClosureExpr : public AbstractClosureExpr {
42024213
/// ... even if the closure has been coerced to return Void by the type
42034214
/// checker. This function does not return true for empty closures.
42044215
bool hasSingleExpressionBody() const {
4205-
return Body.getInt();
4216+
return getSingleExpressionBody();
42064217
}
42074218

42084219
/// Retrieve the body for closure that has a single expression for
4209-
/// its body.
4210-
///
4211-
/// Only valid when \c hasSingleExpressionBody() is true.
4220+
/// its body, or \c nullptr if there is no single expression body.
42124221
Expr *getSingleExpressionBody() const;
42134222

42144223
/// Is this a completely empty closure?

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ ABSTRACT_EXPR(ImplicitConversion, Expr)
183183
EXPR(ForeignObjectConversion, ImplicitConversionExpr)
184184
EXPR(UnevaluatedInstance, ImplicitConversionExpr)
185185
EXPR(UnderlyingToOpaque, ImplicitConversionExpr)
186+
EXPR(Unreachable, ImplicitConversionExpr)
186187
EXPR(DifferentiableFunction, ImplicitConversionExpr)
187188
EXPR(LinearFunction, ImplicitConversionExpr)
188189
EXPR(DifferentiableFunctionExtractOriginal, ImplicitConversionExpr)

include/swift/AST/Stmt.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ class alignas(8) Stmt : public ASTAllocated<Stmt> {
9999
: NumPadBits,
100100
CaseCount : 32
101101
);
102+
103+
SWIFT_INLINE_BITFIELD(ReturnStmt, Stmt, 1,
104+
/// Whether the result is an implied return, e.g for an implicit single
105+
/// expression return.
106+
IsImplied : 1
107+
);
102108

103109
SWIFT_INLINE_BITFIELD_FULL(YieldStmt, Stmt, 32,
104110
: NumPadBits,
@@ -244,7 +250,9 @@ class ReturnStmt : public Stmt {
244250

245251
ReturnStmt(SourceLoc returnLoc, Expr *result, bool isImplicit)
246252
: Stmt(StmtKind::Return, isImplicit), ReturnLoc(returnLoc),
247-
Result(result) {}
253+
Result(result) {
254+
Bits.ReturnStmt.IsImplied = false;
255+
}
248256

249257
public:
250258
static ReturnStmt *createParsed(ASTContext &ctx, SourceLoc returnLoc,
@@ -261,11 +269,25 @@ class ReturnStmt : public Stmt {
261269
return createImplicit(ctx, SourceLoc(), result);
262270
}
263271

272+
/// Create an implicit implied ReturnStmt for a single expression body.
273+
static ReturnStmt *forSingleExprBody(ASTContext &ctx, Expr *result) {
274+
assert(result && "Result must be present to be implied");
275+
auto *RS = createImplicit(ctx, result);
276+
RS->Bits.ReturnStmt.IsImplied = true;
277+
return RS;
278+
}
279+
264280
SourceLoc getReturnLoc() const { return ReturnLoc; }
265281

266282
SourceLoc getStartLoc() const;
267283
SourceLoc getEndLoc() const;
268284

285+
/// Whether the result is an implied return, e.g for an implicit single
286+
/// expression return.
287+
bool isImplied() const {
288+
return Bits.ReturnStmt.IsImplied;
289+
}
290+
269291
bool hasResult() const { return Result != 0; }
270292
Expr *getResult() const {
271293
assert(Result && "ReturnStmt doesn't have a result");

include/swift/AST/TypeCheckRequests.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4128,9 +4128,9 @@ class PreCheckReturnStmtRequest
41284128
bool isCached() const { return true; }
41294129
};
41304130

4131-
/// Performs some pre-checking of a function body, including inserting and
4132-
/// removing implict returns where needed. This request is currently
4133-
/// side-effectful, as it will mutate the body in-place.
4131+
/// Performs some pre-checking of a function body, including inserting implicit
4132+
/// returns where needed. This request is currently side-effectful, as it will
4133+
/// mutate the body in-place.
41344134
///
41354135
/// Note this request is currently uncached as:
41364136
/// - The result will ultimately be cached by TypeCheckFunctionBodyRequest.
@@ -4152,6 +4152,23 @@ class PreCheckFunctionBodyRequest
41524152
BraceStmt *evaluate(Evaluator &evaluator, AbstractFunctionDecl *AFD) const;
41534153
};
41544154

4155+
/// Performs some pre-checking of a closure's body, including inserting implicit
4156+
/// returns where needed. This request is currently side-effectful, as it will
4157+
/// mutate the body in-place. Like PreCheckFunctionBodyRequest, it is currently
4158+
/// uncached.
4159+
class PreCheckClosureBodyRequest
4160+
: public SimpleRequest<PreCheckClosureBodyRequest,
4161+
BraceStmt *(ClosureExpr *),
4162+
RequestFlags::Uncached> {
4163+
public:
4164+
using SimpleRequest::SimpleRequest;
4165+
4166+
private:
4167+
friend SimpleRequest;
4168+
4169+
BraceStmt *evaluate(Evaluator &evaluator, ClosureExpr *closure) const;
4170+
};
4171+
41554172
/// The result of the query for whether a statement can produce a single value.
41564173
class IsSingleValueStmtResult {
41574174
public:

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ SWIFT_REQUEST(TypeChecker, TangentStoredPropertyRequest,
350350
SWIFT_REQUEST(TypeChecker, PreCheckFunctionBodyRequest,
351351
BraceStmt *(AbstractFunctionDecl *),
352352
Uncached, NoLocationInfo)
353+
SWIFT_REQUEST(TypeChecker, PreCheckClosureBodyRequest,
354+
BraceStmt *(ClosureExpr *),
355+
Uncached, NoLocationInfo)
353356
SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyRequest,
354357
BraceStmt *(AbstractFunctionDecl *), SeparatelyCached,
355358
NoLocationInfo)

include/swift/Sema/CompletionContextFinder.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,6 @@ class CompletionContextFinder : public ASTWalker {
7373

7474
PostWalkResult<Expr *> walkToExprPost(Expr *E) override;
7575

76-
/// Check whether code completion expression is located inside of a
77-
/// multi-statement closure.
78-
bool locatedInMultiStmtClosure() const {
79-
return hasContext(ContextKind::MultiStmtClosure);
80-
}
81-
8276
bool locatedInStringInterpolation() const {
8377
return hasContext(ContextKind::StringInterpolation);
8478
}

include/swift/Sema/ConstraintLocator.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,17 @@ class ProtocolConformance;
4747
/// specified error messages when the conversion fails.
4848
///
4949
enum ContextualTypePurpose : uint8_t {
50-
CTP_Unused, ///< No contextual type is specified.
51-
CTP_Initialization, ///< Pattern binding initialization.
52-
CTP_ReturnStmt, ///< Value specified to a 'return' statement.
53-
CTP_ReturnSingleExpr, ///< Value implicitly returned from a function.
54-
CTP_YieldByValue, ///< By-value yield operand.
55-
CTP_YieldByReference, ///< By-reference yield operand.
56-
CTP_ThrowStmt, ///< Value specified to a 'throw' statement.
57-
CTP_DiscardStmt, ///< Value specified to a 'discard' statement.
58-
CTP_EnumCaseRawValue, ///< Raw value specified for "case X = 42" in enum.
59-
CTP_DefaultParameter, ///< Default value in parameter 'foo(a : Int = 42)'.
50+
CTP_Unused, ///< No contextual type is specified.
51+
CTP_Initialization, ///< Pattern binding initialization.
52+
CTP_ReturnStmt, ///< Value specified to a 'return' statement.
53+
CTP_ImpliedReturnStmt, ///< Value from an implied 'return', e.g a single expr
54+
/// function body.
55+
CTP_YieldByValue, ///< By-value yield operand.
56+
CTP_YieldByReference, ///< By-reference yield operand.
57+
CTP_ThrowStmt, ///< Value specified to a 'throw' statement.
58+
CTP_DiscardStmt, ///< Value specified to a 'discard' statement.
59+
CTP_EnumCaseRawValue, ///< Raw value specified for "case X = 42" in enum.
60+
CTP_DefaultParameter, ///< Default value in parameter 'foo(a : Int = 42)'.
6061

6162
/// Default value in @autoclosure parameter
6263
/// 'foo(a : @autoclosure () -> Int = 42)'.
@@ -819,11 +820,13 @@ class LocatorPathElt::TypeParameterRequirement final
819820

820821
class LocatorPathElt::ClosureBody final : public StoredIntegerElement<1> {
821822
public:
822-
ClosureBody(bool hasExplicitReturn = false)
823-
: StoredIntegerElement(ConstraintLocator::ClosureBody, hasExplicitReturn) {}
823+
ClosureBody(bool hasImpliedReturn)
824+
: StoredIntegerElement(ConstraintLocator::ClosureBody, hasImpliedReturn) {}
824825

825-
/// Indicates whether body of the closure has any `return` statements.
826-
bool hasExplicitReturn() const { return bool(getValue()); }
826+
/// Indicates whether body of the closure has an implied `return` statement,
827+
/// this is the case for single expression bodies where the `return` was not
828+
/// written explicitly.
829+
bool hasImpliedReturn() const { return bool(getValue()); }
827830

828831
static bool classof(const LocatorPathElt *elt) {
829832
return elt->getKind() == ConstraintLocator::ClosureBody;

lib/AST/ASTBridging.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,7 @@ BridgedClosureExpr_createParsed(BridgedASTContext cContext,
10191019
auto *out = new (context) ClosureExpr(
10201020
attributes, bracketRange, nullptr, nullptr, asyncLoc, throwsLoc,
10211021
/*FIXME:thrownType=*/nullptr, arrowLoc, inLoc, nullptr, declContext);
1022-
out->setBody(body.unbridged(), true);
1022+
out->setBody(body.unbridged());
10231023
out->setParameterList(params);
10241024
return out;
10251025
}

0 commit comments

Comments
 (0)