Skip to content

Commit 8f3031d

Browse files
CodaFijrose-apple
authored andcommitted
Provide a fix for SR-1571 (#2854)
Lookup can occasionally produce a call to a superclass constructor here that is not in our immediate superclass and we would trust it was completely valid. Instead, reject the notion of creating such a constructor entirely unless its decl can prove it is actually in our superclass.
1 parent 4956ba6 commit 8f3031d

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,21 @@ swift::createDesignatedInitOverride(TypeChecker &tc,
20482048
if (superclassCtor->getGenericParams())
20492049
return nullptr;
20502050

2051+
// Lookup will sometimes give us initializers that are from the ancestors of
2052+
// our immediate superclass. So, from the superclass constructor, we look
2053+
// one level up to the enclosing type context which will either be a class
2054+
// or an extension. We can use the type declared in that context to check
2055+
// if it's our immediate superclass and give up if we didn't.
2056+
//
2057+
// FIXME: Remove this when lookup of initializers becomes restricted to our
2058+
// immediate superclass.
2059+
Type superclassTyInCtor = superclassCtor->getDeclContext()->getDeclaredTypeInContext();
2060+
Type superclassTy = classDecl->getSuperclass();
2061+
NominalTypeDecl *superclassDecl = superclassTy->getAnyNominal();
2062+
if (superclassTyInCtor->getAnyNominal() != superclassDecl) {
2063+
return nullptr;
2064+
}
2065+
20512066
// Determine the initializer parameters.
20522067
auto &ctx = tc.Context;
20532068

@@ -2064,8 +2079,6 @@ swift::createDesignatedInitOverride(TypeChecker &tc,
20642079
//
20652080
// We might have to apply substitutions, if for example we have a declaration
20662081
// like 'class A : B<Int>'.
2067-
auto superclassTy = classDecl->getSuperclass();
2068-
auto *superclassDecl = superclassTy->getAnyNominal();
20692082
if (superclassDecl->isGenericTypeContext()) {
20702083
if (auto *superclassSig = superclassDecl->getGenericSignatureOfContext()) {
20712084
auto *moduleDecl = classDecl->getParentModule();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-parse-verify-swift
2+
3+
protocol P {
4+
init()
5+
}
6+
7+
class A : P { } // expected-error{{initializer requirement 'init()' can only be satisfied by a `required` initializer in non-final class 'A'}}
8+
// No further errors
9+
10+
class B : A {
11+
init(x : Int) {}
12+
}
13+
14+
class C : B { }
15+
16+
class D : B {
17+
init() {
18+
super.init() // expected-error{{missing argument for parameter 'x' in call}}
19+
}
20+
}
21+

0 commit comments

Comments
 (0)