Skip to content

Commit b932739

Browse files
committed
[Sema] Fix throwing super.init() diagnostics
The compiler now diagnoses appropriately the case where a super.init() is marked as throwing while a subclass' initializer isn't marked as throwing nor explicitly calls the super.init().
1 parent 36a15ce commit b932739

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4807,6 +4807,12 @@ ERROR(return_init_non_nil,none,
48074807
"'nil' is the only return value permitted in an initializer",
48084808
())
48094809

4810+
ERROR(implicit_throws_super_init,none,
4811+
"missing call to superclass's initializer; "
4812+
"'super.init' is a throwing initializer and requires either an explicit "
4813+
"call or that this initializer is also marked as 'throws'",
4814+
())
4815+
48104816
ERROR(implicit_async_super_init,none,
48114817
"missing call to superclass's initializer; "
48124818
"'super.init' is 'async' and requires an explicit call",

lib/Sema/TypeCheckStmt.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2236,7 +2236,17 @@ static bool checkSuperInit(ConstructorDecl *fromCtor,
22362236
fromCtor->diagnose(diag::availability_unavailable_implicit_init,
22372237
ctor, superclassDecl->getName());
22382238
}
2239-
2239+
2240+
// Only allowed to synthesize a throwing super.init() call if the init being
2241+
// checked is also throwing.
2242+
if (ctor->hasThrows()) {
2243+
// Diagnose on nonthrowing or rethrowing initializer.
2244+
if (!fromCtor->hasThrows() || fromCtor->hasPolymorphicEffect(EffectKind::Throws)) {
2245+
fromCtor->diagnose(diag::implicit_throws_super_init);
2246+
return true; // considered an error
2247+
}
2248+
}
2249+
22402250
// Not allowed to implicitly generate a super.init() call if the init
22412251
// is async; that would hide the 'await' from the programmer.
22422252
if (ctor->hasAsync()) {

test/Sema/throwing_super_init.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
class ThrowingInitSuperclass {
4+
init() throws { }
5+
}
6+
7+
// Implicitly calling the super.init IS possible here because the initializer
8+
// is a throwing initializer.
9+
class ThrowingInitClass: ThrowingInitSuperclass {
10+
init(simpleArgument: Int) throws { }
11+
}
12+
13+
// Implicitly calling the super.init IS NOT possible here because the
14+
// initializer is not a throwing initializer.
15+
class NonThrowingInitClass: ThrowingInitSuperclass {
16+
init(simpleArgument: Int) { } // expected-error {{missing call to superclass's initializer; 'super.init' is a throwing initializer and requires either an explicit call or that this initializer is also marked as 'throws'}}
17+
}
18+
19+
// Implicitly calling the super.init IS NOT possible here because the
20+
// initializer is a rethrowing initializer, which means it can only
21+
// rethrow errors from its parameters.
22+
class RethrowingInitClass: ThrowingInitSuperclass {
23+
init(throwingArgument: () throws -> Void) rethrows { } // expected-error {{missing call to superclass's initializer; 'super.init' is a throwing initializer and requires either an explicit call or that this initializer is also marked as 'throws'}}
24+
}

0 commit comments

Comments
 (0)