[swift-evolution] [Review] SE-0018 Flexible Memberwise Initialization

Matthew Johnson matthew at anandabits.com
Thu Jan 7 21:37:47 CST 2016


> On Jan 7, 2016, at 8:55 PM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
> 
> The proposal says that "let" properties with inline initializers should be left out of the memberwise initialization, AIUI on the grounds that a manually-written initializer would not be allowed to override the inline initialization:

Yes, this is because Chris insisted that the proposal be pure sugar for something that could be manually written.  This ensures that anyone using memberwise initialization can stop using it in any case where that becomes necessary. 

> 
> class C {
>   let x = 1738
>   init(x: Int = 679) {
>     self.x = x // Error, self.x already initialized
>   }
> }
> 
> However, this is also true for vars. Semantically, if you change 'x' to a var in the above example, you get an initialization followed by an assignment:
> 
> class C {
>   let x = dump(1738)
>   init(x: Int = dump(679)) {
>     self.x = x
>   }
> }
> 
> 	    C() // dumps 1738, then 679
> 
> which, if the initialization has side effects, will likely be surprising. We could say that the memberwise initializer elides the inline initialization of `var`s, on the grounds that initializations ought not to have side effects, but then we're introducing a behavior change in inline initializers for `var`s in the face of `memberwise` initializers that also cannot be replicated by a manually-written initializer. If we make that behavior change for vars, I think it's reasonable, and more orthogonal, to extend the same grace to lets as well. That also simplifies the rules for what appears in the memberwise initializer—there's now only two rules (or one, if we also remove the access control filter, as I've suggested in another subthread).

I agree.  The dual assignment for `var` seems wasteful in addition to potentially surprising and the limitation for `let` is unfortunate.  Of course the same can be said for all initializers that might wish to assign a different value to a `let` or do assign a different value to a `var`.

What you suggest is exactly how I wanted the proposal to work.  Chris was opposed to this approach.  I would be very happy with this change if you can sell Chris on it!  I think many others would be as well. 

In addition to this not being possible to implement manually, Chris explained to me that it is important to the optimizer to be able to assume a `let` with an inline initializer will never have any other value (especially when that inline initializer is a constant value).  Allowing an instance member to be optimized away when initialized with a constant value enables it to be referenced with convenient syntax due to implicit `self`.  It would have never occurred to me to make a true constant value an instance property, but apparently this is a common practice.  And with a guaranteed optimization is makes sense to take advantage of the implicit `self`.  

At the same time, IMO the inability to provide a default value for a property that is only used when it is not initialized manually is a more important issue.  I wish the “inline initializer” worked this way.  

I know the implementation would be a bit more complex - the compiler would have to analyze the body of non-memberwise initializers before synthesizing the inline-initialization if necessary.  But it already emits an “uninitialized member” error message so it already knows which properties are initialized and which are not.  That information may not be available in the right part of the compiler but we do not how to determine this.

This would solve the init / assign problem for `var` and the no overridable default problem for `let` in both existing and memberwise initializers.  It would also mean that memberwise initializers can work this way while still being pure sugar for code that can be written manually.  Unfortunately this seems like something that is not open for change.

Matthew

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160107/55e365a7/attachment-0001.html>


More information about the swift-evolution mailing list