[Pitch] `init` accessors

It benefits the programmer writing the init accessor. You state your assumptions about what the init accessor initializes and depends on, and the compiler will provide error messages if you accidentally initialize or access something you didn't mean to, or forgot to initialize something that you meant to initialize. If you don't get diagnostics in the body of an init accessor and you make a mistake, you'll probably get misleading diagnostics somewhere else (probably in the body of the type's initializer) because the compiler won't have any way to infer that you just forgot to initialize something in the accessor.

Me! I wrote this code without thinking any thing of it (I'm not a numerics expert!). I don't think it's that ridiculous, and even if it is, the example was meant to illustrate the general pattern of computing values from stored properties via computed properties in ways that don't fit the property wrapper model, which I personally have used all over the place in my Swift code, and I suspect others have as well.

EDIT: I have been informed by a numerics expert that degrees are bad! I stand by my point though; I still think a stored value in some representation that is used to compute the same conceptual value in another representation is a very common pattern that doesn't fit into the property wrapper model, it's reasonable to support virtual initialization from any representation, and I can change the proposal example to something else if Angle is actually that distracting :slight_smile:

This proposal doesn't add any expressivity that you cannot already write in some form in your code. Property wrapper definite initialization doesn't add any expressivity either -- you can always manually initialize the backing property wrapper yourself, but people find that annoying / confusing because the backing property wrapper storage is an implementation detail that often isn't otherwise mentioned at all in code using property wrappers. The proposal text also outlines a usability issue with attached macros due to the lack of custom definite initialization behavior:

Furthermore, property-wrapper-like macros cannot achieve the same initializer usability, because any backing storage variables added must be initialized directly instead of supporting initialization through computed properties. For example, the proposed @Observable macro applies a property-wrapper-like transform that turns stored properties into computed properties backed by the observation APIs, but it provides no way to write an initializer using the original property names like the programmer expects:

@Observable
struct Proposal {
  var title: String
  var text: String

  init(title: String, text: String) {
    self.title = title // error: 'self' used before all stored properties are initialized
    self.text = text // error: 'self' used before all stored properties are initialized
  } // error: Return from initializer without initializing all stored properties
}
3 Likes