Following the discussion of SE-0242, it has been brought up that user defined initializers implicitly call all the member initializers for the given struct/class and that this is considered a bug.
Bug here: [SR-10092] Custom initializers always call member initializers · Issue #52494 · apple/swift · GitHub
Given:
func zero() -> Int {
print("hello")
return 0
}
struct X {
var y = zero()
init(y: Int) {
self.y = y
}
}
let x = X(y: 10) // hello
Calling the user defined initializer surprisingly invokes this side effect, but it was never called in the init.
If we look at the lowered init in that example, it looks something like:
init(y: Int) {
// Inserted here to ensure that y is initialized.
self.y = zero()
self.y = y
}
This gets complicated pretty quickly because if we decide to just remove the member init then we could have source compatibility issues where they never initialized the property in the first place. i.e.
init(y: Int) {} // does this now error?
or do we check to ensure that the property is initialized first, and then deleted? If so, how would the following behave:
init(y: Int) {
if y > 0 {
self.y = y // ok, this is initialized now.
} else {
// do we initialize self.y here?
print(self.y) // not initialized yet... do we error here?
}
// do we initialize self.y here just in case?
print(self.y) // could be initialized, could not be... do we error here?
}
This is most definitely going to require a proposal of some sort, but to me what makes the most sense is to only call the member initializers in the default initializer and produce errors in user defined ones (this is almost guaranteed source breaking).
func zero() -> Int {
print("hello")
return 0
}
struct Foo {
var y = zero()
// currently the following is legal...
// error: return from initializer without initializing all stored properties
init(y: Int) {
// self.y = y
}
}
struct Bar {
var y = zero()
}
let foo = Foo(y: 10) // nothing is printed
let bar = Bar() // hello
cc some people who were a part of that discussion: @jrose @xwu @anandabits @nevin (apologies if there was someone I missed).