diff --git a/lib/AST/ConformanceLookup.cpp b/lib/AST/ConformanceLookup.cpp index 4ee498b5ce322..60299b1729f59 100644 --- a/lib/AST/ConformanceLookup.cpp +++ b/lib/AST/ConformanceLookup.cpp @@ -728,6 +728,8 @@ LookupConformanceInModuleRequest::evaluate( ProtocolConformanceRef ModuleDecl::checkConformance(Type type, ProtocolDecl *proto, bool allowMissing) { + assert(!type->hasTypeParameter()); + auto lookupResult = lookupConformance(type, proto, allowMissing); if (lookupResult.isInvalid()) { return ProtocolConformanceRef::forInvalid(); diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index 144ff2888eb51..505aab0f2369c 100644 --- a/lib/IDE/ConformingMethodList.cpp +++ b/lib/IDE/ConformingMethodList.cpp @@ -174,8 +174,19 @@ void ConformingMethodListCallbacks::getMatchingMethods( if (FD->isStatic() || FD->isOperator()) return false; - auto resultTy = T->getTypeOfMember(CurModule, FD, - FD->getResultInterfaceType()); + assert(!T->hasTypeParameter()); + + // T may contain primary archetypes from some fixed generic signature G. + // This might be unrelated to the generic signature of FD. However if + // FD has a generic parameter of its own and it returns a type containing + // that parameter, we want to map it to the corresponding archetype + // from the generic environment of FD, because all we do with the + // resulting type is check conformance. If the conformance is conditional, + // we might run into trouble with really complicated cases but the fake + // archetype setup will mostly work. + auto substitutions = T->getMemberSubstitutionMap( + CurModule, FD, FD->getGenericEnvironment()); + auto resultTy = FD->getResultInterfaceType().subst(substitutions); if (resultTy->is()) return false; diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index ab41da9255e30..d71a6b8397082 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1396,7 +1396,7 @@ static void diagnoseClassWithoutInitializers(ClassDecl *classDecl) { if (auto *superclassDecl = classDecl->getSuperclassDecl()) { auto *decodableProto = C.getProtocol(KnownProtocolKind::Decodable); auto superclassType = superclassDecl->getDeclaredInterfaceType(); - auto ref = classDecl->getParentModule()->checkConformance( + auto ref = classDecl->getParentModule()->lookupConformance( superclassType, decodableProto); if (ref) { // super conforms to Decodable, so we've failed to inherit init(from:). @@ -1425,7 +1425,7 @@ static void diagnoseClassWithoutInitializers(ClassDecl *classDecl) { // likely that the user forgot to override its encode(to:). In this case, // we can produce a slightly different diagnostic to suggest doing so. auto *encodableProto = C.getProtocol(KnownProtocolKind::Encodable); - auto ref = classDecl->getParentModule()->checkConformance( + auto ref = classDecl->getParentModule()->lookupConformance( superclassType, encodableProto); if (ref) { // We only want to produce this version of the diagnostic if the diff --git a/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift b/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift index a26f25bc64c68..c5c0c13673b0e 100644 --- a/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift +++ b/test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift @@ -97,3 +97,13 @@ class EncodableSubWithoutInitialValue : CodableSuper { // expected-error {{class class CodableSubWithInitialValue : CodableSuper { var value2 = 10 } + +class GenericCodableSuper: Decodable {} + +class GenericCodableSub: GenericCodableSuper { +// expected-error@-1 {{class 'GenericCodableSub' has no initializers}} +// expected-note@-2 {{did you mean to override 'init(from:)'?}} +// expected-warning@-2 {{'required' initializer 'init(from:)' must be provided by subclass of 'GenericCodableSuper'; this is an error in Swift 6}} + var t: T + // expected-note@-1 {{stored property 't' without initial value prevents synthesized initializers}} +} \ No newline at end of file