Skip to content

Enforce that checkConformance() is not called with interface types #70990

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/AST/ConformanceLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
15 changes: 13 additions & 2 deletions lib/IDE/ConformingMethodList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ErrorType>())
return false;

Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:).
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,13 @@ class EncodableSubWithoutInitialValue : CodableSuper { // expected-error {{class
class CodableSubWithInitialValue : CodableSuper {
var value2 = 10
}

class GenericCodableSuper<T>: Decodable {}

class GenericCodableSub<T>: GenericCodableSuper<T> {
// 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<T>'; this is an error in Swift 6}}
var t: T
// expected-note@-1 {{stored property 't' without initial value prevents synthesized initializers}}
}