Skip to content

Commit f481a81

Browse files
authored
Merge pull request #36854 from xedin/detect-error-exprs-in-result-builders
[Diagnostics] Allow result build to detect `ErrorExpr`s in the body
2 parents b834f99 + 22a231e commit f481a81

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,13 @@ class PreCheckResultBuilderApplication : public ASTWalker {
18721872
E, DC, /*replaceInvalidRefsWithErrors=*/false);
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+
}
1881+
18751882
if (SuppressDiagnostics)
18761883
transaction.abort();
18771884

lib/Sema/CSFix.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1734,14 +1734,26 @@ bool IgnoreInvalidResultBuilderBody::diagnose(const Solution &solution,
17341734
class PreCheckWalker : public ASTWalker {
17351735
DeclContext *DC;
17361736
DiagnosticTransaction Transaction;
1737+
// Check whether expression(s) in the body of the
1738+
// result builder had any `ErrorExpr`s before pre-check.
1739+
bool FoundErrorExpr = false;
17371740

17381741
public:
17391742
PreCheckWalker(DeclContext *dc)
17401743
: DC(dc), Transaction(dc->getASTContext().Diags) {}
17411744

17421745
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
1746+
// This has to be checked before `preCheckExpression`
1747+
// because pre-check would convert invalid references
1748+
// into `ErrorExpr`s.
1749+
E->forEachChildExpr([&](Expr *expr) {
1750+
FoundErrorExpr |= isa<ErrorExpr>(expr);
1751+
return FoundErrorExpr ? nullptr : expr;
1752+
});
1753+
17431754
auto hasError = ConstraintSystem::preCheckExpression(
17441755
E, DC, /*replaceInvalidRefsWithErrors=*/true);
1756+
17451757
return std::make_pair(false, hasError ? nullptr : E);
17461758
}
17471759

@@ -1755,7 +1767,18 @@ bool IgnoreInvalidResultBuilderBody::diagnose(const Solution &solution,
17551767
}
17561768

17571769
bool diagnosed() const {
1758-
return Transaction.hasErrors();
1770+
// pre-check produced an error.
1771+
if (Transaction.hasErrors())
1772+
return true;
1773+
1774+
// If there were `ErrorExpr`s before pre-check
1775+
// they should have been diagnosed already by parser.
1776+
if (FoundErrorExpr) {
1777+
auto &DE = DC->getASTContext().Diags;
1778+
return DE.hadAnyError();
1779+
}
1780+
1781+
return false;
17591782
}
17601783
};
17611784

test/Constraints/result_builder_diags.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,4 +712,13 @@ struct TuplifiedStructWithInvalidClosure {
712712
0
713713
}
714714
}
715+
716+
@TupleBuilder var errorsDiagnosedByParser: some Any {
717+
if let cond = condition {
718+
tuplify { _ in
719+
self. // expected-error {{expected member name following '.'}}
720+
}
721+
42
722+
}
723+
}
715724
}

0 commit comments

Comments
 (0)