The type of `self` could remain `inout Self` inside the failable initializer. 
The ability to assign nil would be a compiler magic (much like `return nil` is 
compiler magic) that is meant to introduce uniformity to the initialization 
logic.

The idea is to define all different ways initialization can take place and 
expand them to be used uniformly on both `self` and all its members, as well as 
remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
        1. delegating initializer
        2. assigning to self
        3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my 
opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable 
initializers.

#3:  The only thing that can be returned from an initializer is `nil`, which is 
compiler magic, so we can thing of it as a misnomer (because we aren't really 
**returning** anything).

If, for a second, we forget about potential factory initializers, returning 
anything from an initializer doesn't make much sense, because an initializer is 
conceptually meant to bring an existing object in memory to a type-specific 
valid state. This semantic was very explicitly in Objective-C with `[[MyType 
alloc] init]`. Especially since even syntactically, the initializer does not 
specify any return type, the idea of returning from an initializer is 
counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I 
imagine `self = nil`, would largely mean the same (except not needed to return 
immediately and allowing non-self-accessing code to be executed before return). 
Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't 
count) may feel a bit wonky, but not as wonky as returning nil from something 
that is meant to initialize an object in-place and doesn't look like it should 
return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could 
completely flip this logic, but making the initializer essentially a static 
function that returns an object. In this case the initializer could be made to 
specify the return type (that is the supertype of all possible factory-created 
objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

        public factory init(weCool: Bool) -> MyProtocol {
                self = MyImpl() // error: cannot assign to `self` in a factory 
initializer
                self.init(...) // error: cannot make a delegating initializer 
call in a factory initializer
                if weCool {
                        return MyCoolImpl()
                } else {
                        return MyUncoolImpl()
                }
        }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in 
`self.member = value`), which could be extended in a non-factory initializer to 
be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more 
reliable performance guarantee that this member will not be copy-initialized.

> On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote:
> 
> If `self` is not of type `inout Self?`, then what is the type of `self` such 
> that you may assign it a value of `nil`?
> 
> It certainly cannot be of type `inout Self`, unless `Self` conforms to 
> `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` 
> an unlimited number of times–but that has a totally different meaning.
> 
> Could `self` be of type `inout Self!`? Now that implicitly unwrapped 
> optionals are no longer their own type, I’m not sure that’s possible. But 
> even if it were, that seems unintuitive and potentially error-prone.
> 
> So I think Greg is quite right that, to enable this feature, `self` would 
> have to be of type `inout Self?`–which is intriguing but potentially more 
> boilerplatey than the status quo.
> On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> Good point, but not necessarily.
> Since you cannot access `self` before it being fully initialized and since 
> `self` can only be initialized once, this would mean that after `self = nil`, 
> you won't be allowed to access `self` in your initializer at all.You'll be 
> able to do any potential, cleanup though.
> Also, since there can be only one `self = nil`, there's no reason to treat 
> `self` as `inout Self?`, because the only place it can be `nil` is the place 
> it cannot be accessed any more.
> 
> 
>> On Jun 9, 2017, at 7:45 AM, Greg Parker <gpar...@apple.com 
>> <mailto:gpar...@apple.com>> wrote:
>> 
>> 
>>> On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 1. Arbitrary `self` Assignments In Intializers
>>> 
>>> The first ideas is to allow `self = nil` inside failable initializers 
>>> (essentially making `self` look like `inout Self?` instead of `inout Self` 
>>> with magical `return nil`), so that all initializers uniformly can be 
>>> written in `self = ...` form for clarity and convenience purposes. This 
>>> should, theoretically, be nothing but a `defer { return nil }` type of 
>>> rewrite, so I don't see any major difficulties implementing this. This is 
>>> especially useful for failable-initializing enums where the main switch 
>>> simply assigns to self in all cases and the rest of the initializer does 
>>> some post-processing.
>> 
>> I don't see how to avoid source incompatibility and uglification of failable 
>> initializer implementations here. Allowing `self = nil` inside a failable 
>> initializer would require `self` to be an optional. That in turn would 
>> require every use of `self` in the initializer to be nil-checked or forced. 
>> I don't think that loss everywhere outweighs the gain of `self = nil` in 
>> some places.
>> 
>> 
>> -- 
>> Greg Parker     gpar...@apple.com <mailto:gpar...@apple.com>     Runtime 
>> Wrangler
>> 
>> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to