Skip to content

Commit 096c3ec

Browse files
committed
[CS] Avoid delaying application for multi-statement closures
We ought to be able to apply the solution to them immediately now.
1 parent 2524044 commit 096c3ec

File tree

3 files changed

+4
-111
lines changed

3 files changed

+4
-111
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,9 +2087,6 @@ enum class SolutionApplicationToFunctionResult {
20872087
/// Application of the solution failed.
20882088
/// TODO: This should probably go away entirely.
20892089
Failure,
2090-
/// The solution could not be applied immediately, and type checking for
2091-
/// this function should be delayed until later.
2092-
Delay,
20932090
};
20942091

20952092
/// Retrieve the closure type from the constraint system.

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -6453,12 +6453,6 @@ static bool applyTypeToClosureExpr(ConstraintSystem &cs,
64536453
// If we found an explicit ClosureExpr, update its type.
64546454
if (auto CE = dyn_cast<ClosureExpr>(expr)) {
64556455
cs.setType(CE, toType);
6456-
6457-
// If solution application for this closure is delayed, let's write the
6458-
// type into the ClosureExpr directly here, since the visitor won't.
6459-
if (!CE->hasSingleExpressionBody())
6460-
CE->setType(toType);
6461-
64626456
return true;
64636457
}
64646458

@@ -8822,15 +8816,12 @@ namespace {
88228816

88238817
class ExprWalker : public ASTWalker, public SyntacticElementTargetRewriter {
88248818
ExprRewriter &Rewriter;
8825-
SmallVector<ClosureExpr *, 4> ClosuresToTypeCheck;
88268819
SmallVector<Decl *, 4> LocalDeclsToTypeCheck;
88278820

88288821
public:
88298822
ExprWalker(ExprRewriter &Rewriter) : Rewriter(Rewriter) { }
88308823

88318824
~ExprWalker() {
8832-
assert(ClosuresToTypeCheck.empty());
8833-
88348825
// Type-check any local decls encountered.
88358826
for (auto *D : LocalDeclsToTypeCheck)
88368827
TypeChecker::typeCheckDecl(D);
@@ -8849,37 +8840,6 @@ namespace {
88498840
return false;
88508841
}
88518842

8852-
/// Check if there are any closures or tap expressions left to process separately.
8853-
bool hasDelayedTasks() { return !ClosuresToTypeCheck.empty(); }
8854-
8855-
/// Process delayed closure bodies and `Tap` expressions.
8856-
///
8857-
/// \returns true if any part of the processing fails.
8858-
bool processDelayed() {
8859-
bool hadError = false;
8860-
auto &solution = Rewriter.solution;
8861-
auto &cs = solution.getConstraintSystem();
8862-
8863-
while (!ClosuresToTypeCheck.empty()) {
8864-
auto *closure = ClosuresToTypeCheck.pop_back_val();
8865-
// If experimental multi-statement closure support
8866-
// is enabled, solution should have all of required
8867-
// information.
8868-
//
8869-
// Note that in this mode `ClosuresToTypeCheck` acts
8870-
// as a stack because multi-statement closures could
8871-
// have other multi-statement closures in the body.
8872-
hadError |= cs.applySolutionToBody(closure, *this);
8873-
8874-
if (!hadError) {
8875-
TypeChecker::checkClosureAttributes(closure);
8876-
TypeChecker::checkParameterList(closure->getParameters(), closure);
8877-
}
8878-
}
8879-
8880-
return hadError;
8881-
}
8882-
88838843
MacroWalking getMacroWalkingBehavior() const override {
88848844
return MacroWalking::Arguments;
88858845
}
@@ -8959,12 +8919,6 @@ namespace {
89598919

89608920
case SolutionApplicationToFunctionResult::Failure:
89618921
return true;
8962-
8963-
case SolutionApplicationToFunctionResult::Delay: {
8964-
auto closure = cast<ClosureExpr>(fn.getAbstractClosureExpr());
8965-
ClosuresToTypeCheck.push_back(closure);
8966-
return false;
8967-
}
89688922
}
89698923
}
89708924

@@ -9817,31 +9771,8 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
98179771
result.setExpr(resultExpr);
98189772

98199773
if (cs.isDebugMode()) {
9820-
// If target is a multi-statement closure or
9821-
// a tap expression, expression will not be fully
9822-
// type checked until these expressions are visited in
9823-
// processDelayed().
9824-
bool isPartial = false;
9825-
resultExpr->forEachChildExpr([&](Expr *child) -> Expr * {
9826-
if (auto *closure = dyn_cast<ClosureExpr>(child)) {
9827-
if (!closure->hasSingleExpressionBody()) {
9828-
isPartial = true;
9829-
return nullptr;
9830-
}
9831-
}
9832-
if (isa<TapExpr>(child)) {
9833-
isPartial = true;
9834-
return nullptr;
9835-
}
9836-
return child;
9837-
});
9838-
98399774
auto &log = llvm::errs();
9840-
if (isPartial) {
9841-
log << "\n---Partially type-checked expression---\n";
9842-
} else {
9843-
log << "\n---Type-checked expression---\n";
9844-
}
9775+
log << "\n---Type-checked expression---\n";
98459776
resultExpr->dump(log);
98469777
log << "\n";
98479778
}
@@ -9902,29 +9833,6 @@ ConstraintSystem::applySolution(Solution &solution,
99029833
if (!resultTarget)
99039834
return std::nullopt;
99049835

9905-
auto needsPostProcessing = walker.hasDelayedTasks();
9906-
9907-
// Visit closures that have non-single expression bodies, tap expressions,
9908-
// and possibly other types of AST nodes which could only be processed
9909-
// after contextual expression.
9910-
bool hadError = walker.processDelayed();
9911-
9912-
// If any of them failed to type check, bail.
9913-
if (hadError)
9914-
return std::nullopt;
9915-
9916-
if (isDebugMode()) {
9917-
// If we had partially type-checked expressions, lets print
9918-
// fully type-checked target after processDelayed is done.
9919-
auto node = target.getAsASTNode();
9920-
if (node && needsPostProcessing) {
9921-
auto &log = llvm::errs();
9922-
log << "\n---Fully type-checked target---\n";
9923-
node.dump(log);
9924-
log << "\n";
9925-
}
9926-
}
9927-
99289836
rewriter.finalize();
99299837

99309838
return resultTarget;

lib/Sema/CSSyntacticElement.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,21 +2592,9 @@ ConstraintSystem::applySolution(AnyFunctionRef fn,
25922592
}
25932593
assert(closure && "Can only get here with a closure at the moment");
25942594

2595-
// If this closure is checked as part of the enclosing expression, handle
2596-
// that now.
2597-
//
2598-
// Multi-statement closures are handled separately because they need to
2599-
// wait until all of the `ExtInfo` flags are propagated from the context
2600-
// e.g. parameter could be no-escape if closure is applied to a call.
2601-
if (closure->hasSingleExpressionBody()) {
2602-
bool hadError = applySolutionToBody(closure, rewriter);
2603-
return hadError ? SolutionApplicationToFunctionResult::Failure
2604-
: SolutionApplicationToFunctionResult::Success;
2605-
}
2606-
2607-
// Otherwise, we need to delay type checking of the closure until later.
2608-
solution.setExprTypes(closure);
2609-
return SolutionApplicationToFunctionResult::Delay;
2595+
bool hadError = applySolutionToBody(closure, rewriter);
2596+
return hadError ? SolutionApplicationToFunctionResult::Failure
2597+
: SolutionApplicationToFunctionResult::Success;
26102598
}
26112599

26122600
bool ConstraintSystem::applySolutionToBody(

0 commit comments

Comments
 (0)