mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
We have a predicate in ClassDecl, 'inheritsSuperclassInitializers', that is used in a few places to decide if we need to do lookups into a superclass to find all relevant initializers. That's useful, but the actual work being computed in that function is almost identical to the work done in figuring out whether the class has provided all its superclass's /required/ initializers, which is part of the type checker operation 'resolveImplicitConstructors'. Furthermore, 'inheritsSuperclassInitializers' is /already/ calling 'resolveImplicitConstructors' because those implicit constructors might affect the result. Simplify this whole mess and prevent further inconsistencies like the previous commit by just making 'resolveImplicitConstructors' decide whether superclass convenience initializers are inherited. It does make that function more complicated, but with the benefit of not having duplication anymore. No intended user-visible change, except that this bit is now serialized instead of being recomputed, which means the module format changed.
105 lines
3.4 KiB
Swift
105 lines
3.4 KiB
Swift
// RUN: %target-typecheck-verify-swift
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Restrictions on where required can appear
|
|
// -------------------------------------------------------------------------
|
|
required class AC { } // expected-error{{'required' may only be used on 'init' declarations}}
|
|
|
|
class C {
|
|
required init(string s: String) { } // expected-note{{'required' initializer is declared in superclass here}}
|
|
|
|
required var s: String // expected-error{{'required' may only be used on 'init' declarations}}
|
|
|
|
required func f() { } // expected-error{{'required' may only be used on 'init' declarations}}
|
|
}
|
|
|
|
struct S {
|
|
required init() { } // expected-error{{'required' initializer in non-class type 'S'}}
|
|
}
|
|
|
|
enum E {
|
|
required init() { } // expected-error{{'required' initializer in non-class type 'E'}}
|
|
}
|
|
|
|
extension C {
|
|
required convenience init(string2 s: String) { self.init(string:s) } // expected-error{{'required' initializer must be declared directly in class 'C' (not in an extension)}}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Subclass requirements for required
|
|
// -------------------------------------------------------------------------
|
|
class C2 : C { // okay: implicitly defined
|
|
}
|
|
|
|
class C2b : C {
|
|
init() {}
|
|
} // expected-error{{'required' initializer 'init(string:)' must be provided by subclass of 'C'}}{{1-1=\n required init(string s: String) {\n fatalError("init(string:) has not been implemented")\n }\n}}
|
|
|
|
class C3 : C {
|
|
required init(string s: String) { } // expected-note{{overridden required initializer is here}}
|
|
}
|
|
|
|
class C4 : C3 {
|
|
// implicitly required
|
|
init(string s: String) { }
|
|
// expected-error @-1{{'required' modifier must be present on all overrides of a required initializer}}
|
|
// expected-note @-2{{'required' initializer is declared in superclass here}}
|
|
}
|
|
|
|
class C5 : C4 {
|
|
}
|
|
|
|
class C5b : C4 {
|
|
init() {}
|
|
// expected-error{{'required' initializer 'init(string:)' must be provided by subclass of 'C4'}}
|
|
func wibble() { }
|
|
}
|
|
|
|
class C6 : C {
|
|
init() { super.init(string: "") }
|
|
required convenience init(string: String) { self.init() }
|
|
}
|
|
|
|
|
|
class Foo {
|
|
required init() { }
|
|
// expected-note@-1{{'required' initializer is declared in superclass here}}
|
|
// expected-note@-2{{overridden required initializer is here}}
|
|
}
|
|
|
|
class Bar : Foo {
|
|
}
|
|
|
|
class Baz : Bar {
|
|
init(i: Int) { super.init() }
|
|
} // expected-error{{'required' initializer 'init()' must be provided by subclass of 'Bar'}}
|
|
|
|
class Baz2 : Bar {
|
|
init() { super.init() } // expected-error {{'required' modifier must be present on all overrides of a required initializer}}
|
|
}
|
|
|
|
|
|
class HasRequiredConvenienceInit {
|
|
init() {}
|
|
required convenience init(conveniently: Int) { self.init() } // expected-note {{here}}
|
|
}
|
|
|
|
class InheritsAllInits: HasRequiredConvenienceInit {}
|
|
|
|
class InheritsConvenienceInits: HasRequiredConvenienceInit {
|
|
override init() {}
|
|
}
|
|
|
|
class DoesNotInheritConvenienceInits: HasRequiredConvenienceInit {
|
|
init(value: Int) { super.init() }
|
|
} // expected-error {{'required' initializer 'init(conveniently:)' must be provided by subclass of 'HasRequiredConvenienceInit'}}
|
|
|
|
class ProvidesNewConvenienceInit: HasRequiredConvenienceInit {
|
|
init(value: Int) { super.init() }
|
|
required convenience init(conveniently: Int) { self.init(value: 1) }
|
|
}
|
|
|
|
class ProvidesNewDesignatedInit: HasRequiredConvenienceInit {
|
|
required init(conveniently: Int) { super.init() }
|
|
}
|