@@ -911,16 +911,44 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
911911 // before pointer types could be compared.
912912 auto locator = getLocator ();
913913 auto path = locator->getPath ();
914- unsigned toDrop = 0 ;
915- for (const auto &elt : llvm::reverse (path)) {
916- if (!elt.is <LocatorPathElt::OptionalPayload>())
917- break ;
918914
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+ }
921939 }
922940
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+ }
924952
925953 std::optional<Diag<Type, Type>> diagnostic;
926954 if (path.empty ()) {
0 commit comments