Skip to content

Commit 3c5a6f9

Browse files
authored
Merge pull request #41864 from xedin/improvements-for-diagnoseAmbiguity
[ConstraintSystem] Augment `diagnoseAmbiguity` to handle non-expression anchors
2 parents f1c5e07 + ebdef12 commit 3c5a6f9

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1746,7 +1746,12 @@ bool TypeChecker::diagnoseSelfAssignment(const Expr *expr) {
17461746
}
17471747

17481748
bool TrailingClosureAmbiguityFailure::diagnoseAsNote() {
1749-
auto *anchor = castToExpr(getAnchor());
1749+
auto *anchor = getAsExpr(getAnchor());
1750+
// This diagnostic is used opportunistically in `diagnoseAmbiguity`,
1751+
// which means it cannot assume that anchor is always an expression.
1752+
if (!anchor)
1753+
return false;
1754+
17501755
const auto *expr = findParentExpr(anchor);
17511756
auto *callExpr = dyn_cast_or_null<CallExpr>(expr);
17521757
if (!callExpr)

lib/Sema/ConstraintSystem.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4557,7 +4557,7 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef<Solution> solutions) {
45574557
auto &overload = diff.overloads[i];
45584558
auto *locator = overload.locator;
45594559

4560-
Expr *anchor = nullptr;
4560+
ASTNode anchor;
45614561

45624562
// Simplification of member locator would produce a base expression,
45634563
// this is what we want for diagnostics but not for comparisons here
@@ -4567,25 +4567,33 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef<Solution> solutions) {
45674567
// than simplification of `count` would produce `[x]` which is incorrect.
45684568
if (locator->isLastElement<LocatorPathElt::Member>() ||
45694569
locator->isLastElement<LocatorPathElt::ConstructorMember>()) {
4570-
anchor = getAsExpr(locator->getAnchor());
4570+
anchor = locator->getAnchor();
45714571
} else {
4572-
anchor = getAsExpr(simplifyLocatorToAnchor(overload.locator));
4572+
anchor = simplifyLocatorToAnchor(overload.locator);
45734573
}
45744574

4575-
// If we can't resolve the locator to an anchor expression with no path,
4575+
// If we can't resolve the locator to an anchor with no path,
45764576
// we can't diagnose this well.
45774577
if (!anchor)
45784578
continue;
45794579

4580-
auto it = indexMap.find(anchor);
4581-
if (it == indexMap.end())
4582-
continue;
4583-
unsigned index = it->second;
4580+
// Index and Depth is only applicable to expressions.
4581+
unsigned index = 0;
4582+
unsigned depth = 0;
45844583

4585-
auto optDepth = getExprDepth(anchor);
4586-
if (!optDepth)
4587-
continue;
4588-
unsigned depth = *optDepth;
4584+
if (auto *expr = getAsExpr(anchor)) {
4585+
auto it = indexMap.find(expr);
4586+
if (it == indexMap.end())
4587+
continue;
4588+
4589+
index = it->second;
4590+
4591+
auto optDepth = getExprDepth(expr);
4592+
if (!optDepth)
4593+
continue;
4594+
4595+
depth = *optDepth;
4596+
}
45894597

45904598
// If we don't have a name to hang on to, it'll be hard to diagnose this
45914599
// overload.

test/expr/closure/multi_statement.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,26 @@ func test_local_function_capturing_vars() {
234234
}
235235
}
236236

237+
func test_pattern_ambiguity_doesnot_crash_compiler() {
238+
enum E {
239+
case hello(result: Int) // expected-note 2 {{found this candidate}}
240+
case hello(status: Int) // expected-note 2 {{found this candidate}}
241+
}
242+
243+
let _: (E) -> Void = {
244+
switch $0 {
245+
case .hello(_): break // expected-error {{ambiguous use of 'hello'}}
246+
}
247+
}
248+
249+
let _: (E) -> Void = {
250+
switch $0 {
251+
case let E.hello(x): print(x) // expected-error {{ambiguous use of 'hello'}}
252+
default: break
253+
}
254+
}
255+
}
256+
237257
func test_taps_type_checked_with_correct_decl_context() {
238258
struct Path {
239259
func contains<T>(_: T) -> Bool where T: StringProtocol { return false }

0 commit comments

Comments
 (0)