Skip to content

Commit 3474735

Browse files
committed
[ResultBuilders] Allow pre-check to look into single-statement closures
While determining whether result builder body is correct, allow pre-check phase to look into single-statement closures because their bodies participate in type-check and would fail constraint generation if they contain `ErrorExpr`s, so it's better to determine that the body is invalid early and skip result builder application. Resolves: rdar://79746785 (cherry picked from commit 3374500)
1 parent 901fd93 commit 3474735

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,12 +1872,8 @@ class PreCheckResultBuilderApplication : public ASTWalker {
18721872
E, DC, /*replaceInvalidRefsWithErrors=*/true);
18731873
HasError |= transaction.hasErrors();
18741874

1875-
if (!HasError) {
1876-
E->forEachChildExpr([&](Expr *expr) {
1877-
HasError |= isa<ErrorExpr>(expr);
1878-
return HasError ? nullptr : expr;
1879-
});
1880-
}
1875+
if (!HasError)
1876+
HasError |= containsErrorExpr(E);
18811877

18821878
if (SuppressDiagnostics)
18831879
transaction.abort();
@@ -1899,6 +1895,29 @@ class PreCheckResultBuilderApplication : public ASTWalker {
18991895
return std::make_pair(true, S);
19001896
}
19011897

1898+
/// Check whether given expression (including single-statement
1899+
/// closures) contains `ErrorExpr` as one of its sub-expressions.
1900+
bool containsErrorExpr(Expr *expr) {
1901+
bool hasError = false;
1902+
1903+
expr->forEachChildExpr([&](Expr *expr) -> Expr * {
1904+
hasError |= isa<ErrorExpr>(expr);
1905+
if (hasError)
1906+
return nullptr;
1907+
1908+
if (auto *closure = dyn_cast<ClosureExpr>(expr)) {
1909+
if (shouldTypeCheckInEnclosingExpression(closure)) {
1910+
hasError |= containsErrorExpr(closure->getSingleExpressionBody());
1911+
return hasError ? nullptr : expr;
1912+
}
1913+
}
1914+
1915+
return expr;
1916+
});
1917+
1918+
return hasError;
1919+
}
1920+
19021921
/// Ignore patterns.
19031922
std::pair<bool, Pattern*> walkToPatternPre(Pattern *pat) override {
19041923
return { false, pat };

test/Constraints/result_builder_diags.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,4 +727,13 @@ struct TuplifiedStructWithInvalidClosure {
727727
42
728728
}
729729
}
730+
731+
@TupleBuilder var nestedErrorsDiagnosedByParser: some Any {
732+
tuplify(true) { _ in
733+
tuplify { _ in
734+
self. // expected-error {{expected member name following '.'}}
735+
}
736+
42
737+
}
738+
}
730739
}

0 commit comments

Comments
 (0)