@@ -2734,34 +2734,52 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
2734
2734
// overloads of the same declaration.
2735
2735
ConstraintLocator *commonCalleeLocator = nullptr ;
2736
2736
SmallPtrSet<ValueDecl *, 4 > distinctChoices;
2737
- SmallVector<std::pair<const Solution *, const ConstraintFix *>, 4 >
2738
- viableSolutions;
2737
+ SmallVector<const Solution *, 4 > viableSolutions;
2738
+
2739
+ enum class AmbiguityKind {
2740
+ // / There is exactly one fix associated with each candidate.
2741
+ CloseMatch,
2742
+ // / Solution is ambiguous because all candidates had partially matching
2743
+ // / parameter lists.
2744
+ ParameterList,
2745
+ // / General ambiguity failure.
2746
+ General,
2747
+ };
2748
+ auto ambiguityKind = AmbiguityKind::CloseMatch;
2739
2749
2740
2750
bool diagnosable = llvm::all_of (solutions, [&](const Solution &solution) {
2741
2751
ArrayRef<ConstraintFix *> fixes = solution.Fixes ;
2742
2752
2743
- // Currently only support a single fix in a solution,
2744
- // but ultimately should be able to deal with multiple.
2745
- if (fixes.size () != 1 )
2753
+ if (fixes.empty ())
2746
2754
return false ;
2747
2755
2748
- const auto *fix = fixes.front ();
2749
- auto *locator = fix->getLocator ();
2756
+ if (fixes.size () > 1 ) {
2757
+ ambiguityKind = (ambiguityKind == AmbiguityKind::CloseMatch ||
2758
+ ambiguityKind == AmbiguityKind::ParameterList) &&
2759
+ llvm::all_of (fixes, [](const ConstraintFix *fix) -> bool {
2760
+ auto *locator = fix->getLocator ();
2761
+ return locator->findLast <LocatorPathElt::ApplyArgument>().hasValue ();
2762
+ }) ? AmbiguityKind::ParameterList
2763
+ : AmbiguityKind::General;
2764
+ }
2765
+
2766
+ for (const auto *fix: fixes) {
2767
+ auto *locator = fix->getLocator ();
2768
+ // Assignment failures are all about the source expression,
2769
+ // because they treat destination as a contextual type.
2770
+ if (auto *anchor = locator->getAnchor ()) {
2771
+ if (auto *assignExpr = dyn_cast<AssignExpr>(anchor))
2772
+ locator = getConstraintLocator (assignExpr->getSrc ());
2773
+ }
2750
2774
2751
- // Assignment failures are all about the source expression,
2752
- // because they treat destination as a contextual type.
2753
- if ( auto *anchor = locator-> getAnchor ()) {
2754
- if (auto *assignExpr = dyn_cast<AssignExpr>(anchor) )
2755
- locator = getConstraintLocator (assignExpr-> getSrc ()) ;
2775
+ auto *calleeLocator = getCalleeLocator (locator);
2776
+ if (!commonCalleeLocator)
2777
+ commonCalleeLocator = calleeLocator;
2778
+ else if (commonCalleeLocator != calleeLocator )
2779
+ return false ;
2756
2780
}
2757
2781
2758
- auto *calleeLocator = getCalleeLocator (locator);
2759
- if (commonCalleeLocator && commonCalleeLocator != calleeLocator)
2760
- return false ;
2761
-
2762
- commonCalleeLocator = calleeLocator;
2763
-
2764
- auto overload = solution.getOverloadChoiceIfAvailable (calleeLocator);
2782
+ auto overload = solution.getOverloadChoiceIfAvailable (commonCalleeLocator);
2765
2783
if (!overload)
2766
2784
return false ;
2767
2785
@@ -2773,7 +2791,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
2773
2791
// as viable, otherwise we'd produce the same diagnostic multiple
2774
2792
// times, which means that actual problem is elsewhere.
2775
2793
if (distinctChoices.insert (decl).second )
2776
- viableSolutions.push_back ({ &solution, fix} );
2794
+ viableSolutions.push_back (&solution);
2777
2795
return true ;
2778
2796
});
2779
2797
@@ -2787,32 +2805,11 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
2787
2805
{
2788
2806
DiagnosticTransaction transaction (getASTContext ().Diags );
2789
2807
2790
- const auto *fix = viableSolutions.front ().second ;
2791
2808
auto *commonAnchor = commonCalleeLocator->getAnchor ();
2792
2809
auto &DE = getASTContext ().Diags ;
2793
2810
auto name = decl->getFullName ();
2794
2811
2795
- if (fix->getKind () == FixKind::UseSubscriptOperator) {
2796
- auto *UDE = cast<UnresolvedDotExpr>(commonAnchor);
2797
- DE.diagnose (commonAnchor->getLoc (),
2798
- diag::could_not_find_subscript_member_did_you_mean,
2799
- getType (UDE->getBase ()));
2800
- } else if (fix->getKind () == FixKind::TreatRValueAsLValue) {
2801
- DE.diagnose (commonAnchor->getLoc (),
2802
- diag::no_overloads_match_exactly_in_assignment,
2803
- decl->getBaseName ());
2804
- } else if (llvm::all_of (
2805
- viableSolutions,
2806
- [](const std::pair<const Solution *, const ConstraintFix *>
2807
- &fix) {
2808
- auto *locator = fix.second ->getLocator ();
2809
- return locator
2810
- ->isLastElement <LocatorPathElt::ContextualType>();
2811
- })) {
2812
- auto baseName = name.getBaseName ();
2813
- DE.diagnose (commonAnchor->getLoc (), diag::no_candidates_match_result_type,
2814
- baseName.userFacingName (), getContextualType ());
2815
- } else {
2812
+ auto emitGeneralAmbiguityFailure = [&]() {
2816
2813
// Three choices here:
2817
2814
// 1. If this is a special name avoid printing it because
2818
2815
// printing kind is sufficient;
@@ -2839,14 +2836,61 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
2839
2836
diag::no_overloads_match_exactly_in_call_no_labels,
2840
2837
decl->getDescriptiveKind (), name.getBaseName ());
2841
2838
}
2839
+ };
2840
+
2841
+ switch (ambiguityKind) {
2842
+ case AmbiguityKind::CloseMatch:
2843
+ // Handled below
2844
+ break ;
2845
+ case AmbiguityKind::ParameterList: {
2846
+ emitGeneralAmbiguityFailure ();
2847
+
2848
+ for (const auto &viable: viableSolutions) {
2849
+ auto overload = viable->getOverloadChoice (commonCalleeLocator);
2850
+ auto *fn = overload.openedType ->getAs <AnyFunctionType>();
2851
+ assert (fn);
2852
+ DE.diagnose (overload.choice .getDecl ()->getLoc (),
2853
+ diag::candidate_partial_match,
2854
+ fn->getParamListAsString (fn->getParams ()));
2855
+ }
2856
+
2857
+ return true ;
2858
+ }
2859
+ case AmbiguityKind::General:
2860
+ // TODO: Handle general ambiguity here.
2861
+ return false ;
2862
+ }
2863
+
2864
+ auto *fix = viableSolutions.front ()->Fixes .front ();
2865
+ if (fix->getKind () == FixKind::UseSubscriptOperator) {
2866
+ auto *UDE = cast<UnresolvedDotExpr>(commonAnchor);
2867
+ DE.diagnose (commonAnchor->getLoc (),
2868
+ diag::could_not_find_subscript_member_did_you_mean,
2869
+ getType (UDE->getBase ()));
2870
+ } else if (fix->getKind () == FixKind::TreatRValueAsLValue) {
2871
+ DE.diagnose (commonAnchor->getLoc (),
2872
+ diag::no_overloads_match_exactly_in_assignment,
2873
+ decl->getBaseName ());
2874
+ } else if (llvm::all_of (
2875
+ viableSolutions,
2876
+ [](const Solution *viable) {
2877
+ auto *locator = viable->Fixes .front ()->getLocator ();
2878
+ return locator
2879
+ ->isLastElement <LocatorPathElt::ContextualType>();
2880
+ })) {
2881
+ auto baseName = name.getBaseName ();
2882
+ DE.diagnose (commonAnchor->getLoc (), diag::no_candidates_match_result_type,
2883
+ baseName.userFacingName (), getContextualType ());
2884
+ } else {
2885
+ emitGeneralAmbiguityFailure ();
2842
2886
}
2843
2887
2844
2888
for (const auto &viable : viableSolutions) {
2845
2889
// Create scope so each applied solution is rolled back.
2846
2890
ConstraintSystem::SolverScope scope (*this );
2847
- applySolution (*viable. first );
2891
+ applySolution (*viable);
2848
2892
// All of the solutions supposed to produce a "candidate" note.
2849
- diagnosed &= viable. second ->diagnose (/* asNote*/ true );
2893
+ diagnosed &= viable-> Fixes . front () ->diagnose (/* asNote*/ true );
2850
2894
}
2851
2895
2852
2896
// If not all of the fixes produced a note, we can't diagnose this.
0 commit comments