Skip to content

Commit f55e764

Browse files
committed
[Constaint system] Add a predicate for when to check closures in enclosing expr
Introduce a new predicate, shouldTypeCheckInEnclosingExpression(), to determine when the body of a closure should be checked as part of the enclosing expression rather than separately, and use it in the various places where "hasSingleExpressionBody()" was used for that purpose.
1 parent 690d6c4 commit f55e764

File tree

8 files changed

+35
-15
lines changed

8 files changed

+35
-15
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,13 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
17011701
FunctionBuilderBodyPreCheck
17021702
PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval,
17031703
AnyFunctionRef fn) const {
1704+
// We don't want to do the precheck if it will already have happened in
1705+
// the enclosing expression.
1706+
bool skipPrecheck = false;
1707+
if (auto closure = dyn_cast_or_null<ClosureExpr>(
1708+
fn.getAbstractClosureExpr()))
1709+
skipPrecheck = shouldTypeCheckInEnclosingExpression(closure);
1710+
17041711
return PreCheckFunctionBuilderApplication(fn, false).run();
17051712
}
17061713

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5787,9 +5787,9 @@ static bool applyTypeToClosureExpr(ConstraintSystem &cs,
57875787
if (auto CE = dyn_cast<ClosureExpr>(expr)) {
57885788
cs.setType(CE, toType);
57895789

5790-
// If this is not a single-expression closure, write the type into the
5791-
// ClosureExpr directly here, since the visitor won't.
5792-
if (!CE->hasSingleExpressionBody())
5790+
// If this closure isn't type-checked in its enclosing expression, write
5791+
// theg type into the ClosureExpr directly here, since the visitor won't.
5792+
if (!shouldTypeCheckInEnclosingExpression(CE))
57935793
CE->setType(toType);
57945794

57955795
return true;

lib/Sema/CSClosure.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,13 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution(
336336
}
337337

338338
return SolutionApplicationToFunctionResult::Success;
339+
339340
}
341+
assert(closure && "Can only get here with a closure at the moment");
340342

341-
// If there is a single-expression body, transform that body now.
342-
if (fn.hasSingleExpressionBody()) {
343+
// If this closure is checked as part of the enclosing expression, handle
344+
// that now.
345+
if (shouldTypeCheckInEnclosingExpression(closure)) {
343346
ClosureConstraintApplication application(
344347
solution, closure, closureFnType->getResult(), rewriteTarget);
345348
application.visit(fn.getBody());

lib/Sema/CSGen.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2248,7 +2248,8 @@ namespace {
22482248
// as potential hole right away.
22492249
resultTy = CS.createTypeVariable(
22502250
resultLoc,
2251-
closure->hasSingleExpressionBody() ? 0 : TVO_CanBindToHole);
2251+
shouldTypeCheckInEnclosingExpression(closure)
2252+
? 0 : TVO_CanBindToHole);
22522253
}
22532254
}
22542255

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7157,14 +7157,13 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
71577157
}
71587158
}
71597159

7160-
bool hasReturn = hasExplicitResult(closure);
7160+
// If this closure should be type-checked as part of this expression,
7161+
// generate constraints for it now.
71617162
auto &ctx = getASTContext();
7162-
// If this is a multi-statement closure its body doesn't participate
7163-
// in type-checking.
7164-
if (closure->hasSingleExpressionBody()) {
7163+
if (shouldTypeCheckInEnclosingExpression(closure)) {
71657164
if (generateConstraints(closure, closureType->getResult()))
71667165
return false;
7167-
} else if (!hasReturn) {
7166+
} else if (!hasExplicitResult(closure)) {
71687167
// If this closure has an empty body and no explicit result type
71697168
// let's bind result type to `Void` since that's the only type empty body
71707169
// can produce. Otherwise, if (multi-statement) closure doesn't have

lib/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5487,6 +5487,12 @@ BraceStmt *applyFunctionBuilderTransform(
54875487
constraints::SolutionApplicationTarget)>
54885488
rewriteTarget);
54895489

5490+
/// Determine whether the given closure expression should be type-checked
5491+
/// within the context of its enclosing expression. Otherwise, it will be
5492+
/// separately type-checked once its enclosing expression has determined all
5493+
/// of the parameter and result types without looking at the body.
5494+
bool shouldTypeCheckInEnclosingExpression(ClosureExpr *expr);
5495+
54905496
} // end namespace swift
54915497

54925498
#endif // LLVM_SWIFT_SEMA_CONSTRAINT_SYSTEM_H

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,8 @@ static void findAvailabilityFixItNodes(SourceRange ReferenceRange,
11281128
[](ASTNode Node, ASTWalker::ParentTy Parent) {
11291129
if (Expr *ParentExpr = Parent.getAsExpr()) {
11301130
auto *ParentClosure = dyn_cast<ClosureExpr>(ParentExpr);
1131-
if (!ParentClosure || !ParentClosure->hasSingleExpressionBody()) {
1131+
if (!ParentClosure ||
1132+
!ParentClosure->wasTypeCheckedInEnclosingContext()) {
11321133
return false;
11331134
}
11341135
} else if (auto *ParentStmt = Parent.getAsStmt()) {

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,9 +1320,8 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) {
13201320
if (hadParameterError)
13211321
return false;
13221322

1323-
// If the closure has a multi-statement body, we don't walk into it
1324-
// here.
1325-
if (!closure->hasSingleExpressionBody())
1323+
// If we won't be checking the body of the closure, don't walk into it here.
1324+
if (!shouldTypeCheckInEnclosingExpression(closure))
13261325
return false;
13271326

13281327
// Update the current DeclContext to be the closure we're about to
@@ -4058,3 +4057,7 @@ HasDynamicCallableAttributeRequest::evaluate(Evaluator &evaluator,
40584057
return type->hasDynamicCallableAttribute();
40594058
});
40604059
}
4060+
4061+
bool swift::shouldTypeCheckInEnclosingExpression(ClosureExpr *expr) {
4062+
return expr->hasSingleExpressionBody();
4063+
}

0 commit comments

Comments
 (0)