Skip to content

Commit ebdef12

Browse files
committed
[ContraintSystem] Augment diagnoseAmbiguity to diagnose non-expression ambiguities
Since constraint solver can now handle statements, patterns, and declarations, it's possible to that ambiguity could be detected in a non-expression context, for example - pattern matching in switch statements. Augment `diagnoseAmbiguity` to accept overloads with non-expression anchors and diagnose them in order of their appearance in a solution.
1 parent 613fdca commit ebdef12

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

lib/Sema/ConstraintSystem.cpp

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

4504-
Expr *anchor = nullptr;
4504+
ASTNode anchor;
45054505

45064506
// Simplification of member locator would produce a base expression,
45074507
// this is what we want for diagnostics but not for comparisons here
@@ -4511,25 +4511,33 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef<Solution> solutions) {
45114511
// than simplification of `count` would produce `[x]` which is incorrect.
45124512
if (locator->isLastElement<LocatorPathElt::Member>() ||
45134513
locator->isLastElement<LocatorPathElt::ConstructorMember>()) {
4514-
anchor = getAsExpr(locator->getAnchor());
4514+
anchor = locator->getAnchor();
45154515
} else {
4516-
anchor = getAsExpr(simplifyLocatorToAnchor(overload.locator));
4516+
anchor = simplifyLocatorToAnchor(overload.locator);
45174517
}
45184518

4519-
// If we can't resolve the locator to an anchor expression with no path,
4519+
// If we can't resolve the locator to an anchor with no path,
45204520
// we can't diagnose this well.
45214521
if (!anchor)
45224522
continue;
45234523

4524-
auto it = indexMap.find(anchor);
4525-
if (it == indexMap.end())
4526-
continue;
4527-
unsigned index = it->second;
4524+
// Index and Depth is only applicable to expressions.
4525+
unsigned index = 0;
4526+
unsigned depth = 0;
45284527

4529-
auto optDepth = getExprDepth(anchor);
4530-
if (!optDepth)
4531-
continue;
4532-
unsigned depth = *optDepth;
4528+
if (auto *expr = getAsExpr(anchor)) {
4529+
auto it = indexMap.find(expr);
4530+
if (it == indexMap.end())
4531+
continue;
4532+
4533+
index = it->second;
4534+
4535+
auto optDepth = getExprDepth(expr);
4536+
if (!optDepth)
4537+
continue;
4538+
4539+
depth = *optDepth;
4540+
}
45334541

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

test/expr/closure/multi_statement.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,14 @@ func test_local_function_capturing_vars() {
236236

237237
func test_pattern_ambiguity_doesnot_crash_compiler() {
238238
enum E {
239-
case hello(result: Int) // expected-note {{found this candidate}}
240-
case hello(status: Int) // expected-note {{found this candidate}}
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+
}
241247
}
242248

243249
let _: (E) -> Void = {

0 commit comments

Comments
 (0)