[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().
This commit is contained in:
Visckmart
2023-09-25 17:25:23 -03:00
parent 36a15ceaf4
commit b93273951f
3 changed files with 41 additions and 1 deletions

View File

@@ -4807,6 +4807,12 @@ ERROR(return_init_non_nil,none,
"'nil' is the only return value permitted in an initializer",
())
ERROR(implicit_throws_super_init,none,
"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'",
())
ERROR(implicit_async_super_init,none,
"missing call to superclass's initializer; "
"'super.init' is 'async' and requires an explicit call",

View File

@@ -2236,7 +2236,17 @@ static bool checkSuperInit(ConstructorDecl *fromCtor,
fromCtor->diagnose(diag::availability_unavailable_implicit_init,
ctor, superclassDecl->getName());
}
// Only allowed to synthesize a throwing super.init() call if the init being
// checked is also throwing.
if (ctor->hasThrows()) {
// Diagnose on nonthrowing or rethrowing initializer.
if (!fromCtor->hasThrows() || fromCtor->hasPolymorphicEffect(EffectKind::Throws)) {
fromCtor->diagnose(diag::implicit_throws_super_init);
return true; // considered an error
}
}
// Not allowed to implicitly generate a super.init() call if the init
// is async; that would hide the 'await' from the programmer.
if (ctor->hasAsync()) {

View File

@@ -0,0 +1,24 @@
// RUN: %target-typecheck-verify-swift
class ThrowingInitSuperclass {
init() throws { }
}
// Implicitly calling the super.init IS possible here because the initializer
// is a throwing initializer.
class ThrowingInitClass: ThrowingInitSuperclass {
init(simpleArgument: Int) throws { }
}
// Implicitly calling the super.init IS NOT possible here because the
// initializer is not a throwing initializer.
class NonThrowingInitClass: ThrowingInitSuperclass {
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'}}
}
// Implicitly calling the super.init IS NOT possible here because the
// initializer is a rethrowing initializer, which means it can only
// rethrow errors from its parameters.
class RethrowingInitClass: ThrowingInitSuperclass {
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'}}
}