The compiler does not lower
init(_ wrappedValue: Int = 0) {
self.wrappedValue = wrappedValue
}
to
init(_ wrappedValue: Int) {
self.wrappedValue = wrappedValue
}
init() {
self.init(0)
}
Because otherwise the number of overloads the compiler has to generate grows exponentially for each optional parameter, among other reasons. For a method with 5 optional parameters, the compiler would need to generate 32 different signatures.
With that said, PropertyWrapper
clearly does not conform to EmptyInitializable
.
What actually happens is that there is only one overload, but for each optional parameter, a thunk is generated to compute the value of that parameter.
init(_ wrappedValue: Int) {
self.wrappedValue = wrappedValue
}
func defaultValueForArgument0OfInit() {
return 0
}
There is also a bit of metadata that tells the compiler to generate calls to that thunk, when the caller has not provided all arguments. The call PropertyWrapper()
is lowered to PropertyWrapper(defaultValueForArgument0OfInit())
. You can see the compiled code in godbolt.org.
If you are calling init
through a protocol, the call is dynamically dispatched, so compiler doesn't even know which implementation will be called, let alone whether it needs to pass the default values of optional parameters.
Of course, the compiler could be designed in other ways that make this possible, but asking why it hasn't been designed in those ways, isn't really answerable, unless you are being very specific.
Side note: since you created a protocol just for the types that can be initialised without parameters, I recommend reading Protocols are more than Bags of Syntax.