Skip to content

Commit 3765a59

Browse files
committed
[CSDiagnostics] Generic argument mismatches should always mention the container types
(cherry picked from commit a8146d6)
1 parent 33fd724 commit 3765a59

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
@@ -904,16 +904,44 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
904904
// before pointer types could be compared.
905905
auto locator = getLocator();
906906
auto path = locator->getPath();
907-
unsigned toDrop = 0;
908-
for (const auto &elt : llvm::reverse(path)) {
909-
if (!elt.is<LocatorPathElt::OptionalPayload>())
910-
break;
911907

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+
}
914932
}
915933

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+
}
917945

918946
std::optional<Diag<Type, Type>> diagnostic;
919947
if (path.empty()) {

0 commit comments

Comments
 (0)