@@ -2776,45 +2776,61 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
2776
2776
2777
2777
auto &DE = cs.getASTContext ().Diags ;
2778
2778
2779
- llvm::SmallDenseMap<TypeVariableType *, SmallVector<Type, 4 >> conflicts;
2779
+ llvm::SmallDenseMap<TypeVariableType *,
2780
+ std::pair<GenericTypeParamType *, SourceLoc>, 4 >
2781
+ genericParams;
2782
+ // Consider only representative type variables shared across
2783
+ // all of the solutions.
2784
+ for (auto *typeVar : cs.getTypeVariables ()) {
2785
+ if (auto *GP = typeVar->getImpl ().getGenericParameter ()) {
2786
+ auto *locator = typeVar->getImpl ().getLocator ();
2787
+ auto *repr = cs.getRepresentative (typeVar);
2788
+ // If representative is another generic parameter let's
2789
+ // use its generic parameter type instead of originator's,
2790
+ // but it's possible that generic parameter is equated to
2791
+ // some other type e.g.
2792
+ //
2793
+ // func foo<T>(_: T) -> T {}
2794
+ //
2795
+ // In this case when reference to function `foo` is "opened"
2796
+ // type variable representing `T` would be equated to
2797
+ // type variable representing a result type of the reference.
2798
+ if (auto *reprGP = repr->getImpl ().getGenericParameter ())
2799
+ GP = reprGP;
2800
+
2801
+ genericParams[repr] = {GP, locator->getAnchor ()->getLoc ()};
2802
+ }
2803
+ }
2780
2804
2781
- for (const auto &binding : solutions[0 ].typeBindings ) {
2782
- auto *typeVar = binding.first ;
2805
+ llvm::SmallDenseMap<std::pair<GenericTypeParamType *, SourceLoc>,
2806
+ SmallVector<Type, 4 >>
2807
+ conflicts;
2783
2808
2784
- if (!typeVar->getImpl ().getGenericParameter ())
2785
- continue ;
2809
+ for (const auto &entry : genericParams) {
2810
+ auto *typeVar = entry.first ;
2811
+ auto GP = entry.second ;
2786
2812
2787
2813
llvm::SmallSetVector<Type, 4 > arguments;
2788
- arguments.insert (binding.second );
2789
-
2790
- if (!llvm::all_of (solutions.slice (1 ), [&](const Solution &solution) {
2791
- auto binding = solution.typeBindings .find (typeVar);
2792
- if (binding == solution.typeBindings .end ())
2793
- return false ;
2794
-
2795
- // Contextual opaque result type is uniquely identified by
2796
- // declaration it's associated with, so we have to compare
2797
- // declarations instead of using pointer equality on such types.
2798
- if (auto *opaque =
2799
- binding->second ->getAs <OpaqueTypeArchetypeType>()) {
2800
- auto *decl = opaque->getDecl ();
2801
- arguments.remove_if ([&](Type argType) -> bool {
2802
- if (auto *otherOpaque =
2803
- argType->getAs <OpaqueTypeArchetypeType>()) {
2804
- return decl == otherOpaque->getDecl ();
2805
- }
2806
- return false ;
2807
- });
2814
+ for (const auto &solution : solutions) {
2815
+ auto type = solution.typeBindings .lookup (typeVar);
2816
+ // Contextual opaque result type is uniquely identified by
2817
+ // declaration it's associated with, so we have to compare
2818
+ // declarations instead of using pointer equality on such types.
2819
+ if (auto *opaque = type->getAs <OpaqueTypeArchetypeType>()) {
2820
+ auto *decl = opaque->getDecl ();
2821
+ arguments.remove_if ([&](Type argType) -> bool {
2822
+ if (auto *otherOpaque = argType->getAs <OpaqueTypeArchetypeType>()) {
2823
+ return decl == otherOpaque->getDecl ();
2808
2824
}
2825
+ return false ;
2826
+ });
2827
+ }
2809
2828
2810
- arguments.insert (binding->second );
2811
- return true ;
2812
- }))
2813
- continue ;
2814
-
2815
- if (arguments.size () > 1 ) {
2816
- conflicts[typeVar].append (arguments.begin (), arguments.end ());
2829
+ arguments.insert (type);
2817
2830
}
2831
+
2832
+ if (arguments.size () > 1 )
2833
+ conflicts[GP].append (arguments.begin (), arguments.end ());
2818
2834
}
2819
2835
2820
2836
auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * {
@@ -2831,8 +2847,10 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
2831
2847
2832
2848
bool diagnosed = false ;
2833
2849
for (auto &conflict : conflicts) {
2834
- auto *typeVar = conflict.first ;
2835
- auto *locator = typeVar->getImpl ().getLocator ();
2850
+ SourceLoc loc;
2851
+ GenericTypeParamType *GP;
2852
+
2853
+ std::tie (GP, loc) = conflict.first ;
2836
2854
auto conflictingArguments = conflict.second ;
2837
2855
2838
2856
llvm::SmallString<64 > arguments;
@@ -2857,10 +2875,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
2857
2875
},
2858
2876
[&OS] { OS << " vs. " ; });
2859
2877
2860
- auto *anchor = locator->getAnchor ();
2861
- DE.diagnose (anchor->getLoc (),
2862
- diag::conflicting_arguments_for_generic_parameter,
2863
- typeVar->getImpl ().getGenericParameter (), OS.str ());
2878
+ DE.diagnose (loc, diag::conflicting_arguments_for_generic_parameter, GP,
2879
+ OS.str ());
2864
2880
diagnosed = true ;
2865
2881
}
2866
2882
0 commit comments