@@ -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()) {
@@ -1009,6 +1037,34 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
1009
1037
break;
1010
1038
}
1011
1039
1040
+ case ConstraintLocator::Member: {
1041
+ auto *memberLoc = getConstraintLocator(anchor, path);
1042
+ auto selectedOverload = getOverloadChoiceIfAvailable(memberLoc);
1043
+ if (!selectedOverload)
1044
+ return false;
1045
+
1046
+ auto baseTy = selectedOverload->choice.getBaseType()->getRValueType();
1047
+ auto *memberRef = selectedOverload->choice.getDecl();
1048
+
1049
+ if (Mismatches.size() == 1) {
1050
+ auto mismatchIdx = Mismatches.front();
1051
+ auto actualArgTy = getActual()->getGenericArgs()[mismatchIdx];
1052
+ auto requiredArgTy = getRequired()->getGenericArgs()[mismatchIdx];
1053
+
1054
+ emitDiagnostic(diag::types_not_equal_in_decl_ref, memberRef, baseTy,
1055
+ actualArgTy, requiredArgTy);
1056
+ emitDiagnosticAt(memberRef, diag::decl_declared_here, memberRef);
1057
+ return true;
1058
+ }
1059
+
1060
+ emitDiagnostic(
1061
+ diag::cannot_reference_conditional_member_on_base_multiple_mismatches,
1062
+ memberRef, baseTy);
1063
+ emitDiagnosticAt(memberRef, diag::decl_declared_here, memberRef);
1064
+ emitNotesForMismatches();
1065
+ return true;
1066
+ }
1067
+
1012
1068
default:
1013
1069
break;
1014
1070
}
0 commit comments