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