Here's a version of your code that doesn't involve modules:
import UIKit
struct S: CustomStringConvertible {
var inited = false
init() {
inited = true
print("S.init")
}
var description: String {
precondition(inited)
return "S description, inited: \(inited)"
}
}
class Parent: UIView {
private // comment / uncomment this line
override init(frame: CGRect) {
super.init(frame: frame)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class Child: Parent {
let a = S()
}
func test() {
let c = Child()
print(c.a)
}
@main class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
test()
return true
}
}
with the line "comment / uncomment this line" commented out (so the initialiser is not private) everything works OK. with this line left as is (so the initialiser is private) the code still compiles ok - but generates some bogus code: the code where "S" variable initialiser could be bypassed – this is clearly wrong.
There's some dodginess in how UIKit "init" operates under the hood. This is likely to do with obj-c <-> swift interop and how when you call .init() it automatically calls "init(frame: .zero)" under the hood (perhaps in some extension)? If you have enough time and motivation you may create another minimal example that replicates this bug without using UIKit / UIViews, would be interesting to know if you can replicate it without involving obj-c or if obj-c is the necessary ingredient here.
PS. your original example could be fixed by making "override init(frame: CGRect)" public (or just remove both initialisers from Parent class (and remove the funny initializable business). I believe it is the same issue as in the version that doesn't use modules.