Skip to content

Commit df44c4f

Browse files
committed
[ConstraintSystem] Fix non-determinism in diagnoseAmbiguity
Simplification of member locator would produce a base expression, this is what we want for diagnostics but not for comparisons in `diagnoseAmbiguity` because base expression is located at a different depth which would lead to incorrect results if both reference and base expression are ambiguous e.g. `test[x].count` if both `[x]` and `count` are ambiguous than simplification of `count` would produce `[x]` which is incorrect. This is the test-case (already in the suite) that exibits this behavior: ``` func test_ambiguity_with_placeholders(pairs: [(rank: Int, count: Int)]) -> Bool { return pairs[<#^ARG^#>].count == 2 } ``` Here subscript would either return a tuple or `ArraySlice` and `count` is ambiguous because both have it.
1 parent ff7de78 commit df44c4f

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4230,10 +4230,25 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef<Solution> solutions) {
42304230

42314231
for (unsigned i = 0, n = diff.overloads.size(); i != n; ++i) {
42324232
auto &overload = diff.overloads[i];
4233+
auto *locator = overload.locator;
4234+
4235+
Expr *anchor = nullptr;
4236+
4237+
// Simplification of member locator would produce a base expression,
4238+
// this is what we want for diagnostics but not for comparisons here
4239+
// because base expression is located at a different depth which would
4240+
// lead to incorrect results if both reference and base expression are
4241+
// ambiguous e.g. `test[x].count` if both `[x]` and `count` are ambiguous
4242+
// than simplification of `count` would produce `[x]` which is incorrect.
4243+
if (locator->isLastElement<LocatorPathElt::Member>() ||
4244+
locator->isLastElement<LocatorPathElt::ConstructorMember>()) {
4245+
anchor = getAsExpr(locator->getAnchor());
4246+
} else {
4247+
anchor = getAsExpr(simplifyLocatorToAnchor(overload.locator));
4248+
}
42334249

42344250
// If we can't resolve the locator to an anchor expression with no path,
42354251
// we can't diagnose this well.
4236-
auto *anchor = getAsExpr(simplifyLocatorToAnchor(overload.locator));
42374252
if (!anchor)
42384253
continue;
42394254

0 commit comments

Comments
 (0)