@@ -904,16 +904,44 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
904
904
// before pointer types could be compared.
905
905
auto locator = getLocator ();
906
906
auto path = locator->getPath ();
907
- unsigned toDrop = 0 ;
908
- for (const auto &elt : llvm::reverse (path)) {
909
- if (!elt.is <LocatorPathElt::OptionalPayload>())
910
- break ;
911
907
912
- // Disregard optional payload element to look at its source.
913
- ++toDrop;
908
+ // If there are generic types involved, we need to find
909
+ // the outermost generic types and report on them instead
910
+ // of their arguments.
911
+ // For example:
912
+ //
913
+ // <expr> -> contextual type
914
+ // -> generic type S<[Int]>
915
+ // -> generic type S<[String]>
916
+ // -> generic argument #0
917
+ //
918
+ // Is going to have from/to types as `[Int]` and `[String]` but
919
+ // the diagnostic should mention `S<[Int]>` and `S<[String]>`
920
+ // because it refers to a contextual type location.
921
+ if (locator->isLastElement <LocatorPathElt::GenericArgument>()) {
922
+ for (unsigned i = 0 ; i < path.size (); ++i) {
923
+ if (auto genericType = path[i].getAs <LocatorPathElt::GenericType>()) {
924
+ ASSERT (i + 1 < path.size ());
925
+
926
+ fromType = resolveType (genericType->getType ());
927
+ toType = resolveType (
928
+ path[i + 1 ].castTo <LocatorPathElt::GenericType>().getType ());
929
+ break ;
930
+ }
931
+ }
914
932
}
915
933
916
- path = path.drop_back (toDrop);
934
+ while (!path.empty ()) {
935
+ auto last = path.back ();
936
+ if (last.is <LocatorPathElt::OptionalPayload>() ||
937
+ last.is <LocatorPathElt::GenericType>() ||
938
+ last.is <LocatorPathElt::GenericArgument>()) {
939
+ path = path.drop_back ();
940
+ continue ;
941
+ }
942
+
943
+ break ;
944
+ }
917
945
918
946
std::optional<Diag<Type, Type>> diagnostic;
919
947
if (path.empty ()) {
0 commit comments