Skip to content

Commit 995a0e7

Browse files
authored
Merge pull request #11281 from xedin/rdar-24329052
2 parents 7ab2d08 + bfbbcc1 commit 995a0e7

File tree

3 files changed

+104
-5
lines changed

3 files changed

+104
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ ERROR(cannot_convert_default_arg_value_nil,none,
340340
ERROR(cannot_convert_argument_value,none,
341341
"cannot convert value of type %0 to expected argument type %1",
342342
(Type,Type))
343+
ERROR(cannot_convert_argument_value_generic,none,
344+
"cannot convert value of type %0 (%1) to expected argument type %2 (%3)",
345+
(Type, StringRef, Type, StringRef))
346+
343347
ERROR(cannot_convert_argument_value_protocol,none,
344348
"argument type %0 does not conform to expected type %1", (Type, Type))
345349
ERROR(cannot_convert_partial_argument_value_protocol,none,
@@ -2548,6 +2552,8 @@ ERROR(generic_type_requires_arguments,none,
25482552
"reference to generic type %0 requires arguments in <...>", (Type))
25492553
NOTE(generic_type_declared_here,none,
25502554
"generic type %0 declared here", (Identifier))
2555+
NOTE(descriptive_generic_type_declared_here,none,
2556+
"%0 declared here", (StringRef))
25512557

25522558
WARNING(use_of_void_pointer,none,
25532559
"Unsafe%0Pointer<Void> has been replaced by Unsafe%0RawPointer", (StringRef))

lib/Sema/CSDiag.cpp

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,7 @@ suggestPotentialOverloads(SourceLoc loc, bool isResult) {
18601860
/// archetype that has argument type errors, diagnose that error and
18611861
/// return true.
18621862
bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) {
1863+
TypeChecker &TC = CS.TC;
18631864
Type argType = CS.getType(badArgExpr);
18641865

18651866
// FIXME: For protocol argument types, could add specific error
@@ -1876,23 +1877,70 @@ bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) {
18761877
argType, archetypesMap))
18771878
return false;
18781879

1880+
auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * {
1881+
auto *env = archetype->getGenericEnvironment();
1882+
auto paramType = env->mapTypeOutOfContext(archetype);
1883+
1884+
if (auto *GTPT = paramType->getAs<GenericTypeParamType>())
1885+
return GTPT->getDecl();
1886+
1887+
if (auto *DMT = paramType->getAs<DependentMemberType>())
1888+
return DMT->getAssocType();
1889+
1890+
return nullptr;
1891+
};
1892+
1893+
auto describeGenericType = [&](ValueDecl *genericParam,
1894+
bool includeName = false) -> std::string {
1895+
if (!genericParam)
1896+
return "";
1897+
1898+
Decl *parent = nullptr;
1899+
if (auto *AT = dyn_cast<AssociatedTypeDecl>(genericParam)) {
1900+
parent = AT->getProtocol();
1901+
} else {
1902+
auto *dc = genericParam->getDeclContext();
1903+
parent = dc->getInnermostDeclarationDeclContext();
1904+
}
1905+
1906+
if (!parent)
1907+
return "";
1908+
1909+
llvm::SmallString<64> result;
1910+
llvm::raw_svector_ostream OS(result);
1911+
1912+
OS << Decl::getDescriptiveKindName(genericParam->getDescriptiveKind());
1913+
1914+
if (includeName && genericParam->hasName())
1915+
OS << " '" << genericParam->getBaseName() << "'";
1916+
1917+
OS << " of ";
1918+
OS << Decl::getDescriptiveKindName(parent->getDescriptiveKind());
1919+
if (auto *decl = dyn_cast<ValueDecl>(parent)) {
1920+
if (decl->hasName())
1921+
OS << " '" << decl->getFullName() << "'";
1922+
}
1923+
1924+
return OS.str();
1925+
};
1926+
18791927
for (auto pair : archetypesMap) {
1880-
auto archetype = pair.first->castTo<ArchetypeType>();
1928+
auto paramArchetype = pair.first->castTo<ArchetypeType>();
18811929
auto substitution = pair.second;
18821930

18831931
// FIXME: Add specific error for not subclass, if the archetype has a superclass?
18841932

18851933
// Check for optional near miss.
18861934
if (auto argOptType = substitution->getOptionalObjectType()) {
1887-
if (CS.TC.isSubstitutableFor(argOptType, archetype, CS.DC)) {
1935+
if (CS.TC.isSubstitutableFor(argOptType, paramArchetype, CS.DC)) {
18881936
CS.TC.diagnose(badArgExpr->getLoc(), diag::missing_unwrap_optional,
18891937
argType);
18901938
foundFailure = true;
1891-
continue;
1939+
break;
18921940
}
18931941
}
1894-
1895-
for (auto proto : archetype->getConformsTo()) {
1942+
1943+
for (auto proto : paramArchetype->getConformsTo()) {
18961944
if (!CS.TC.conformsToProtocol(substitution, proto, CS.DC,
18971945
ConformanceCheckFlags::InExpression)) {
18981946
if (substitution->isEqual(argType)) {
@@ -1905,9 +1953,38 @@ bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) {
19051953
argType, substitution, proto->getDeclaredType());
19061954
}
19071955
foundFailure = true;
1956+
break;
19081957
}
19091958
}
1959+
1960+
if (auto *argArchetype = substitution->getAs<ArchetypeType>()) {
1961+
// Produce this diagnostic only if the names
1962+
// of the generic parameters are the same.
1963+
if (argArchetype->getName() != paramArchetype->getName())
1964+
continue;
1965+
1966+
auto *paramDecl = getGenericTypeDecl(paramArchetype);
1967+
auto *argDecl = getGenericTypeDecl(argArchetype);
1968+
1969+
if (!paramDecl || !argDecl)
1970+
continue;
1971+
1972+
TC.diagnose(badArgExpr->getLoc(),
1973+
diag::cannot_convert_argument_value_generic, argArchetype,
1974+
describeGenericType(argDecl), paramArchetype,
1975+
describeGenericType(paramDecl));
1976+
1977+
TC.diagnose(paramDecl, diag::descriptive_generic_type_declared_here,
1978+
describeGenericType(paramDecl, true));
1979+
1980+
TC.diagnose(argDecl, diag::descriptive_generic_type_declared_here,
1981+
describeGenericType(argDecl, true));
1982+
1983+
foundFailure = true;
1984+
break;
1985+
}
19101986
}
1987+
19111988
return foundFailure;
19121989
}
19131990

test/Constraints/generics.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,3 +480,19 @@ public struct S5 {
480480
g(models: arr)
481481
}
482482
}
483+
484+
// rdar://problem/24329052 - QoI: call argument archetypes not lining up leads to ambiguity errors
485+
486+
struct S_24329052<T> { // expected-note {{generic parameter 'T' of generic struct 'S_24329052' declared here}}
487+
var foo: (T) -> Void
488+
// expected-note@+1 {{generic parameter 'T' of instance method 'bar(_:)' declared here}}
489+
func bar<T>(_ v: T) { foo(v) }
490+
// expected-error@-1 {{cannot convert value of type 'T' (generic parameter of instance method 'bar(_:)') to expected argument type 'T' (generic parameter of generic struct 'S_24329052')}}
491+
}
492+
493+
extension Sequence {
494+
var rdar24329052: (Element) -> Void { fatalError() }
495+
// expected-note@+1 {{generic parameter 'Element' of instance method 'foo24329052(_:)' declared here}}
496+
func foo24329052<Element>(_ v: Element) { rdar24329052(v) }
497+
// expected-error@-1 {{cannot convert value of type 'Element' (generic parameter of instance method 'foo24329052(_:)') to expected argument type 'Self.Element' (associated type of protocol 'Sequence')}}
498+
}

0 commit comments

Comments
 (0)