Skip to content

Commit 651d4f8

Browse files
authored
Merge pull request #70236 from DougGregor/required-inits-69965
Diagnose *all* cases where a subclass fails to override a required init
2 parents a4fe719 + 257a51e commit 651d4f8

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
826826
static void diagnoseMissingRequiredInitializer(
827827
ClassDecl *classDecl,
828828
ConstructorDecl *superInitializer,
829+
bool downgradeToWarning,
829830
ASTContext &ctx) {
830831
// Find the location at which we should insert the new initializer.
831832
SourceLoc insertionLoc;
@@ -906,6 +907,7 @@ static void diagnoseMissingRequiredInitializer(
906907
ctx.Diags.diagnose(insertionLoc, diag::required_initializer_missing,
907908
superInitializer->getName(),
908909
superInitializer->getDeclContext()->getDeclaredInterfaceType())
910+
.warnUntilSwiftVersionIf(downgradeToWarning, 6)
909911
.fixItInsert(insertionLoc, initializerText);
910912

911913
ctx.Diags.diagnose(findNonImplicitRequiredInit(superInitializer),
@@ -1172,10 +1174,11 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
11721174
bool defaultInitable =
11731175
areAllStoredPropertiesDefaultInitializable(ctx.evaluator, decl);
11741176

1175-
// We can't define these overrides if we have any uninitialized
1176-
// stored properties.
1177-
if (!defaultInitable && !foundDesignatedInit)
1178-
return;
1177+
// In cases where we can't define any overrides, we used to suppress
1178+
// diagnostics about missing required initializers. Now we emit diagnostics,
1179+
// but downgrade them to warnings prior to Swift 6.
1180+
bool downgradeRequiredInitsToWarning =
1181+
!defaultInitable && !foundDesignatedInit;
11791182

11801183
SmallVector<ConstructorDecl *, 4> nonOverriddenSuperclassCtors;
11811184
collectNonOveriddenSuperclassInits(decl, nonOverriddenSuperclassCtors);
@@ -1187,8 +1190,10 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
11871190
if (superclassCtor->isRequired()) {
11881191
assert(superclassCtor->isInheritable() &&
11891192
"factory initializers cannot be 'required'");
1190-
if (!decl->inheritsSuperclassInitializers())
1191-
diagnoseMissingRequiredInitializer(decl, superclassCtor, ctx);
1193+
if (!decl->inheritsSuperclassInitializers()) {
1194+
diagnoseMissingRequiredInitializer(
1195+
decl, superclassCtor, downgradeRequiredInitsToWarning, ctx);
1196+
}
11921197
}
11931198
continue;
11941199
}
@@ -1204,12 +1209,18 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
12041209

12051210
// Diagnose a missing override of a required initializer.
12061211
if (superclassCtor->isRequired() && !inheritDesignatedInits) {
1207-
diagnoseMissingRequiredInitializer(decl, superclassCtor, ctx);
1212+
diagnoseMissingRequiredInitializer(
1213+
decl, superclassCtor, downgradeRequiredInitsToWarning, ctx);
12081214
continue;
12091215
}
12101216

12111217
// A designated or required initializer has not been overridden.
12121218

1219+
// We can't define any overrides if we have any uninitialized
1220+
// stored properties.
1221+
if (!defaultInitable && !foundDesignatedInit)
1222+
continue;
1223+
12131224
bool alreadyDeclared = false;
12141225

12151226
auto results = decl->lookupDirect(DeclBaseName::createConstructor());
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-frontend -emit-module-path %t/MyModule.swiftmodule %t/Inputs/MyModule.swift
5+
6+
// RUN: %target-swift-frontend -typecheck -verify -I %t %t/test.swift
7+
8+
//--- Inputs/MyModule.swift
9+
open class MySuperclassA {
10+
required public init() { }
11+
internal init(boop: Bool) {}
12+
}
13+
14+
//--- test.swift
15+
import MyModule
16+
17+
class MySubclassA: MySuperclassA {
18+
// expected-warning{{'required' initializer 'init()' must be provided by subclass of 'MySuperclassA'; this is an error in Swift 6}}
19+
var hi: String
20+
}

test/decl/protocol/special/coding/class_codable_inheritance_diagnostics.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class DecodableSuper : Decodable {
6363

6464
// expected-note@+1 {{did you mean to override 'init(from:)'?}}{{+1:1-1=\noverride init(from decoder: Decoder) throws {\n <#code#>\n\}}}
6565
class DecodableSubWithoutInitialValue : DecodableSuper { // expected-error {{class 'DecodableSubWithoutInitialValue' has no initializers}}
66+
// expected-warning{{'required' initializer 'init(from:)' must be provided by subclass of 'DecodableSuper'}}
6667
var value2: Int // expected-note {{stored property 'value2' without initial value prevents synthesized initializers}}
6768
}
6869

@@ -78,6 +79,7 @@ class CodableSuper : Codable {
7879

7980
// expected-note@+1 {{did you mean to override 'init(from:)' and 'encode(to:)'?}}{{+1:1-1=\noverride init(from decoder: Decoder) throws {\n <#code#>\n\}\n\noverride func encode(to encoder: Encoder) throws {\n <#code#>\n\}}}
8081
class CodableSubWithoutInitialValue : CodableSuper { // expected-error {{class 'CodableSubWithoutInitialValue' has no initializers}}
82+
// expected-warning{{'required' initializer 'init(from:)' must be provided by subclass of 'CodableSuper'; this is an error in Swift 6}}
8183
var value2: Int // expected-note {{stored property 'value2' without initial value prevents synthesized initializers}}
8284
}
8385

@@ -86,6 +88,7 @@ class CodableSubWithoutInitialValue : CodableSuper { // expected-error {{class '
8688
//
8789
// expected-note@+1 {{did you mean to override 'init(from:)'?}}{{+1:1-1=\noverride init(from decoder: Decoder) throws {\n <#code#>\n\}}}
8890
class EncodableSubWithoutInitialValue : CodableSuper { // expected-error {{class 'EncodableSubWithoutInitialValue' has no initializers}}
91+
// expected-warning{{'required' initializer 'init(from:)' must be provided by subclass of 'CodableSuper'; this is an error in Swift 6}}
8992
var value2: Int // expected-note {{stored property 'value2' without initial value prevents synthesized initializers}}
9093

9194
override func encode(to: Encoder) throws {}

0 commit comments

Comments
 (0)