Skip to content

Commit a8146d6

Browse files
committed
[CSDiagnostics] Generic argument mismatches should always mention the container types
1 parent c4e4d4d commit a8146d6

File tree

1 file changed

+35
-7
lines changed

1 file changed

+35
-7
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)