Skip to content

Commit b1eec26

Browse files
committed
[AST] Add a enum for type checking state of ClosureExpr's body
1 parent 0ec7a91 commit b1eec26

File tree

8 files changed

+45
-22
lines changed

8 files changed

+45
-22
lines changed

include/swift/AST/Expr.h

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3759,7 +3759,25 @@ class SerializedAbstractClosureExpr : public SerializedLocalDeclContext {
37593759
/// { [weak c] (a : Int) -> Int in a + c!.getFoo() }
37603760
/// \endcode
37613761
class ClosureExpr : public AbstractClosureExpr {
3762+
public:
3763+
enum class BodyState {
3764+
/// The body was parsed, but not ready for type checking because
3765+
/// the closure parameters haven't been type checked.
3766+
Parsed,
3767+
3768+
/// The type of the closure itself was type checked. But the body has not
3769+
/// been type checked yet.
3770+
ReadyForTypeChecking,
3771+
3772+
/// The body was typechecked with the enclosing closure.
3773+
/// i.e. single expression closure or function builder closure.
3774+
TypeCheckedAtOnce,
3775+
3776+
/// The body was type checked separately from the enclosing closure.
3777+
SeparatelyTypeChecked,
3778+
};
37623779

3780+
private:
37633781
/// The range of the brackets of the capture list, if present.
37643782
SourceRange BracketRange;
37653783

@@ -3783,8 +3801,7 @@ class ClosureExpr : public AbstractClosureExpr {
37833801
SourceLoc InLoc;
37843802

37853803
/// The explicitly-specified result type.
3786-
llvm::PointerIntPair<TypeExpr *, 1, bool>
3787-
ExplicitResultTypeAndSeparatelyChecked;
3804+
llvm::PointerIntPair<TypeExpr *, 2, BodyState> ExplicitResultTypeAndBodyState;
37883805

37893806
/// The body of the closure, along with a bit indicating whether it
37903807
/// was originally just a single expression.
@@ -3799,7 +3816,7 @@ class ClosureExpr : public AbstractClosureExpr {
37993816
BracketRange(bracketRange),
38003817
CapturedSelfDecl(capturedSelfDecl),
38013818
ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
3802-
ExplicitResultTypeAndSeparatelyChecked(explicitResultType, false),
3819+
ExplicitResultTypeAndBodyState(explicitResultType, BodyState::Parsed),
38033820
Body(nullptr) {
38043821
setParameterList(params);
38053822
Bits.ClosureExpr.HasAnonymousClosureVars = false;
@@ -3854,15 +3871,13 @@ class ClosureExpr : public AbstractClosureExpr {
38543871

38553872
Type getExplicitResultType() const {
38563873
assert(hasExplicitResultType() && "No explicit result type");
3857-
return ExplicitResultTypeAndSeparatelyChecked.getPointer()
3858-
->getInstanceType();
3874+
return ExplicitResultTypeAndBodyState.getPointer()->getInstanceType();
38593875
}
38603876
void setExplicitResultType(Type ty);
38613877

38623878
TypeRepr *getExplicitResultTypeRepr() const {
38633879
assert(hasExplicitResultType() && "No explicit result type");
3864-
return ExplicitResultTypeAndSeparatelyChecked.getPointer()
3865-
->getTypeRepr();
3880+
return ExplicitResultTypeAndBodyState.getPointer()->getTypeRepr();
38663881
}
38673882

38683883
/// Determine whether the closure has a single expression for its
@@ -3904,14 +3919,20 @@ class ClosureExpr : public AbstractClosureExpr {
39043919
/// captured non-weakly).
39053920
bool capturesSelfEnablingImplictSelf() const;
39063921

3907-
/// Whether this closure's body was type checked separately from its
3908-
/// enclosing expression.
3909-
bool wasSeparatelyTypeChecked() const {
3910-
return ExplicitResultTypeAndSeparatelyChecked.getInt();
3922+
3923+
/// Get the type checking state of this closure's body.
3924+
BodyState getBodyState() const {
3925+
return ExplicitResultTypeAndBodyState.getInt();
3926+
}
3927+
void setBodyState(BodyState v) {
3928+
ExplicitResultTypeAndBodyState.setInt(v);
39113929
}
39123930

3913-
void setSeparatelyTypeChecked(bool flag = true) {
3914-
ExplicitResultTypeAndSeparatelyChecked.setInt(flag);
3931+
/// Whether this closure's body is/was type checked separately from its
3932+
/// enclosing expression.
3933+
bool isSeparatelyTypeChecked() const {
3934+
return getBodyState() == BodyState::SeparatelyTypeChecked ||
3935+
getBodyState() == BodyState::ReadyForTypeChecking;
39153936
}
39163937

39173938
static bool classof(const Expr *E) {

lib/AST/ASTWalker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
825825

826826
// If the closure was separately type checked and we don't want to
827827
// visit separately-checked closure bodies, bail out now.
828-
if (expr->wasSeparatelyTypeChecked() &&
828+
if (expr->isSeparatelyTypeChecked() &&
829829
!Walker.shouldWalkIntoSeparatelyCheckedClosure(expr))
830830
return expr;
831831

lib/AST/Expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,7 @@ bool ClosureExpr::capturesSelfEnablingImplictSelf() const {
19751975

19761976
void ClosureExpr::setExplicitResultType(Type ty) {
19771977
assert(ty && !ty->hasTypeVariable());
1978-
ExplicitResultTypeAndSeparatelyChecked.getPointer()
1978+
ExplicitResultTypeAndBodyState.getPointer()
19791979
->setType(MetatypeType::get(ty));
19801980
}
19811981

lib/Sema/CSClosure.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,13 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution(
345345
ClosureConstraintApplication application(
346346
solution, closure, closureFnType->getResult(), rewriteTarget);
347347
application.visit(fn.getBody());
348+
closure->setBodyState(ClosureExpr::BodyState::TypeCheckedAtOnce);
348349

349350
return SolutionApplicationToFunctionResult::Success;
350351
}
351352

352353
// Otherwise, we need to delay type checking of the closure until later.
353354
solution.setExprTypes(closure);
355+
closure->setBodyState(ClosureExpr::BodyState::ReadyForTypeChecking);
354356
return SolutionApplicationToFunctionResult::Delay;
355357
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
8686

8787
bool walkToDeclPre(Decl *D) override {
8888
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
89-
return !closure->wasSeparatelyTypeChecked();
89+
return !closure->isSeparatelyTypeChecked();
9090
return false;
9191
}
9292

@@ -1497,7 +1497,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
14971497
// Don't walk into nested decls.
14981498
bool walkToDeclPre(Decl *D) override {
14991499
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
1500-
return !closure->wasSeparatelyTypeChecked();
1500+
return !closure->isSeparatelyTypeChecked();
15011501
return false;
15021502
}
15031503

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1136,7 +1136,7 @@ static void findAvailabilityFixItNodes(SourceRange ReferenceRange,
11361136
if (Expr *ParentExpr = Parent.getAsExpr()) {
11371137
auto *ParentClosure = dyn_cast<ClosureExpr>(ParentExpr);
11381138
if (!ParentClosure ||
1139-
ParentClosure->wasSeparatelyTypeChecked()) {
1139+
ParentClosure->isSeparatelyTypeChecked()) {
11401140
return false;
11411141
}
11421142
} else if (auto *ParentStmt = Parent.getAsStmt()) {

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,7 +2008,7 @@ class FunctionSyntacticDiagnosticWalker : public ASTWalker {
20082008
performSyntacticExprDiagnostics(expr, dcStack.back(), /*isExprStmt=*/false);
20092009

20102010
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
2011-
if (closure->wasSeparatelyTypeChecked()) {
2011+
if (closure->isSeparatelyTypeChecked()) {
20122012
dcStack.push_back(closure);
20132013
return {true, expr};
20142014
}
@@ -2019,7 +2019,7 @@ class FunctionSyntacticDiagnosticWalker : public ASTWalker {
20192019

20202020
Expr *walkToExprPost(Expr *expr) override {
20212021
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
2022-
if (closure->wasSeparatelyTypeChecked()) {
2022+
if (closure->isSeparatelyTypeChecked()) {
20232023
assert(dcStack.back() == closure);
20242024
dcStack.pop_back();
20252025
}

lib/Sema/TypeCheckStmt.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ namespace {
143143
// If the closure was type checked within its enclosing context,
144144
// we need to walk into it with a new sequence.
145145
// Otherwise, it'll have been separately type-checked.
146-
if (!CE->wasSeparatelyTypeChecked())
146+
if (!CE->isSeparatelyTypeChecked())
147147
CE->getBody()->walk(ContextualizeClosures(CE));
148148

149149
TypeChecker::computeCaptures(CE);
@@ -1976,7 +1976,7 @@ bool TypeChecker::typeCheckClosureBody(ClosureExpr *closure) {
19761976
if (body) {
19771977
closure->setBody(body, closure->hasSingleExpressionBody());
19781978
}
1979-
closure->setSeparatelyTypeChecked();
1979+
closure->setBodyState(ClosureExpr::BodyState::SeparatelyTypeChecked);
19801980
return HadError;
19811981
}
19821982

0 commit comments

Comments
 (0)