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