Skip to content

Commit 449ab73

Browse files
[ConstraintSystem] Disambiguate cases of argument/param mismatches involving generic functions
1 parent cc29dc5 commit 449ab73

File tree

1 file changed

+56
-7
lines changed

1 file changed

+56
-7
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2765,6 +2765,9 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
27652765
ParameterList,
27662766
/// General ambiguity failure.
27672767
General,
2768+
/// Argument mismatch ambiguity where each solution has the same
2769+
/// argument mismatch fixes for the same call.
2770+
ArgumentMismatch
27682771
};
27692772
auto ambiguityKind = AmbiguityKind::CloseMatch;
27702773

@@ -2775,16 +2778,52 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
27752778
return false;
27762779

27772780
if (fixes.size() > 1) {
2778-
ambiguityKind = (ambiguityKind == AmbiguityKind::CloseMatch ||
2779-
ambiguityKind == AmbiguityKind::ParameterList) &&
2781+
// Attempt to disambiguite in cases where the argument matches
2782+
// involves tuple mismatches. e.g.
2783+
// func t<T, U>(_: (T, U), _: (U, T)) {}
2784+
// func useTuples(_ x: Int, y: Float) {
2785+
// t((x, y), (x, y))
2786+
// }
2787+
// So fixes are ambiguous in all solutions.
2788+
if ((ambiguityKind == AmbiguityKind::CloseMatch ||
2789+
ambiguityKind == AmbiguityKind::ArgumentMismatch) &&
27802790
llvm::all_of(fixes, [](const ConstraintFix *fix) -> bool {
2781-
auto *locator = fix->getLocator();
2782-
return locator->findLast<LocatorPathElt::ApplyArgument>().hasValue();
2783-
}) ? AmbiguityKind::ParameterList
2784-
: AmbiguityKind::General;
2791+
return fix->getKind() == FixKind::AllowTupleTypeMismatch;
2792+
})) {
2793+
ambiguityKind = AmbiguityKind::ArgumentMismatch;
2794+
} else {
2795+
ambiguityKind =
2796+
(ambiguityKind == AmbiguityKind::CloseMatch ||
2797+
ambiguityKind == AmbiguityKind::ArgumentMismatch ||
2798+
ambiguityKind == AmbiguityKind::ParameterList) &&
2799+
llvm::all_of(
2800+
fixes,
2801+
[](const ConstraintFix *fix) -> bool {
2802+
auto *locator = fix->getLocator();
2803+
return locator
2804+
->findLast<LocatorPathElt::ApplyArgument>()
2805+
.hasValue();
2806+
})
2807+
? AmbiguityKind::ParameterList
2808+
: AmbiguityKind::General;
2809+
}
2810+
}
2811+
2812+
if (fixes.size() == 1) {
2813+
// Attempt to disambiguite in cases where all the solutions
2814+
// produces the same fixes for diferent generic arguments e.g.
2815+
// func f<T>(_: T, _: T) {}
2816+
// f(Int(1), Float(1))
2817+
//
2818+
ambiguityKind =
2819+
((ambiguityKind == AmbiguityKind::CloseMatch ||
2820+
ambiguityKind == AmbiguityKind::ArgumentMismatch) &&
2821+
fixes.front()->getKind() == FixKind::AllowArgumentTypeMismatch)
2822+
? AmbiguityKind::ArgumentMismatch
2823+
: AmbiguityKind::CloseMatch;
27852824
}
27862825

2787-
for (const auto *fix: fixes) {
2826+
for (const auto *fix : fixes) {
27882827
auto *locator = fix->getLocator();
27892828
// Assignment failures are all about the source expression,
27902829
// because they treat destination as a contextual type.
@@ -2816,6 +2855,15 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
28162855
return true;
28172856
});
28182857

2858+
if (ambiguityKind == AmbiguityKind::ArgumentMismatch &&
2859+
viableSolutions.size() == 1) {
2860+
// Let's apply the solution so the contextual generic types
2861+
// are available in the system for diagnostics.
2862+
applySolution(*viableSolutions[0]);
2863+
solutions.front().Fixes.front()->diagnose(/*asNote*/ false);
2864+
return true;
2865+
}
2866+
28192867
if (!diagnosable || viableSolutions.size() < 2)
28202868
return false;
28212869

@@ -2860,6 +2908,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
28602908
};
28612909

28622910
switch (ambiguityKind) {
2911+
case AmbiguityKind::ArgumentMismatch:
28632912
case AmbiguityKind::CloseMatch:
28642913
// Handled below
28652914
break;

0 commit comments

Comments
 (0)