[CS] Use callee locators for fix ambiguities

Currently we check that the fixes share the same anchor, however this
doesn't account for the case where, given an ApplyExpr, one fix is
anchored on its function expr, and another is anchored on the apply
itself (because the former fix might be looking at the callee's
requirements, and the latter fix might be looking at an argument of
the call).

This commit changes the logic such that we check that fixes share the
same callee locator, which covers the above case. In addition, now
that we have the callee locator, we can use this to find the overload
directly.
This commit is contained in:
Hamish Knight
2019-05-15 20:31:53 +01:00
committed by Hamish Knight
parent 894a1e50bf
commit 63df26a498
2 changed files with 10 additions and 23 deletions

View File

@@ -2443,9 +2443,9 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
// Problems related to fixes forming ambiguous solution set
// could only be diagnosed (at the moment), if all of the fixes
// are attached to the same anchor, which means they fix
// different overloads of the same declaration.
Expr *commonAnchor = nullptr;
// have the same callee locator, which means they fix different
// overloads of the same declaration.
ConstraintLocator *commonCalleeLocator = nullptr;
SmallPtrSet<ValueDecl *, 4> distinctChoices;
SmallVector<std::pair<const Solution *, const ConstraintFix *>, 4>
viableSolutions;
@@ -2459,21 +2459,17 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
return false;
const auto *fix = fixes.front();
if (commonAnchor && commonAnchor != fix->getAnchor())
auto *calleeLocator = getCalleeLocator(fix->getAnchor());
if (commonCalleeLocator && commonCalleeLocator != calleeLocator)
return false;
commonAnchor = fix->getAnchor();
commonCalleeLocator = calleeLocator;
SmallVector<SelectedOverload, 2> overloads;
solution.getOverloadChoices(commonAnchor, overloads);
// There is unfortunately no way, at the moment, to figure out
// what declaration the fix is attached to, so we have to make
// sure that there is only one declaration associated with common
// anchor to be sure that the right problem is being diagnosed.
if (overloads.size() != 1)
auto overload = solution.getOverloadChoiceIfAvailable(calleeLocator);
if (!overload)
return false;
auto *decl = getOverloadDecl(overloads.front());
auto *decl = getOverloadDecl(*overload);
if (!decl)
return false;
@@ -2496,6 +2492,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
DiagnosticTransaction transaction(TC.Diags);
const auto *fix = viableSolutions.front().second;
auto *commonAnchor = commonCalleeLocator->getAnchor();
if (fix->getKind() == FixKind::UseSubscriptOperator) {
auto *UDE = cast<UnresolvedDotExpr>(commonAnchor);
TC.diagnose(commonAnchor->getLoc(),