[swift-evolution] [Draft] Abolish IUO type
Chris Willmore
cwillmore at apple.com
Wed Mar 16 23:01:00 CDT 2016
Thanks for the thoughtful response, Chris. Comments inline. I’ve updated the draft linked below to reflect your feedback.
> On Mar 16, 2016, at 5:01 PM, Chris Lattner <clattner at apple.com> wrote:
>
> On Mar 15, 2016, at 10:03 PM, Chris Willmore via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> Hi, swift-evolution,
>>
>> Some colleagues and I have been working on a proposal <https://github.com/cwillmor/swift-evolution/blob/master/proposals/0000-abolish-iuo.md> to remove the ImplicitlyUnwrappedOptional type from Swift and replace it with an IUO decl attribute. Please have a look; I would greatly appreciate any comments you have before I push this proposal forward.
>>
>> https://github.com/cwillmor/swift-evolution/blob/master/proposals/0000-abolish-iuo.md <https://github.com/cwillmor/swift-evolution/blob/master/proposals/0000-abolish-iuo.md>
> You already know this, but I am +100 on this proposal. We definitely need to “nerf” IUO, to get to a more predictable and robust model.
>
> Some minor comments on the writing below. The most significant one is that I think that describing this in terms of an IUO attribute (which is an internal implementation detail) makes the proposal more confusing than necessary for the non-compiler hackers. :-)
Well, IUO is no longer a type, so what do we call it? I agree that it’s weird to call it an attribute when there’s no way to spell it explicitly as such, but I’m at a loss for alternatives. Maybe we could just say that such a declaration is implicitly unwrapped (forced? unwrappable? forceable?), or declares an implicitly unwrapped property/function/variable. Anyway, I’ve changed “declaration with the IUO attribute” to “IUO declaration” in all places but the first occurrence in my revision.
>>
>> <https://github.com/cwillmor/swift-evolution/blob/89971a8162eba3aeb238d47772cda295a02cc585/proposals/0000-abolish-iuo.md#proposed-solution>Proposed solution
>> I propose demoting implicitly unwrapped optionals from being a first-class type in the Swift type system to being an attribute on declarations in Swift. This attribute will be allowed in the following locations:
>>
>> property and variable declarations
>> initializer declarations
>> function declarations
> + Function decls includes the result type as well as the parameter decls, but not a varargs element type.
> + Subscripts.
Good call, added. I added “parameter declarations” as a line item rather than qualify the function-declarations line (and repeat the qualification for initializers, methods, subscripts).
>> Declarations that are marked with the IUO attribute must have optional type.
>>
> Is the IUO attribute actually user exposed in any way, or is it an internal compiler detail? I would expect us to continue to use and prefer (e.g. in the ASTPrinter) the T! syntax.
Re the comment above, should this be rewritten as “Implicitly unwrapped declarations must have optional type”?
>> A reference to a variable or property with the IUO attribute may be implicitly forced (i.e. converted to the underlying type) when being type-checked, thus replicating the current behavior of a declaration with IUO type. Likewise, the result of a function application or initialization where the callee is a reference to a function declaration with the IUO attribute may be implicitly forced.
>>
> For clarity in the wording, I’d suggest something along the lines of:
>
> "A reference to a variable or property with the IUO attribute prefers to bind to an optional, but may also be implicitly forced …”
Yep, makes sense; added.
>
>> The appearance of ! at the end of a property or variable type no longer indicates that the property or variable has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has the IUO attribute. The appearance of ! at the end of the return type of a function indicates that the function has optional return type and the IUO attribute. The use of init! in an initializer declaration indicates that the initializer is failable and has the IUO attribute.
>>
> This again is talking about the compiler implementation details.
Possible resolution: “… (2) the declaration may be implicitly unwrapped”? Likewise “… the return value of the function may be implicitly unwrapped".
>
>> Because there is no longer an IUO type, types with nested IUOs are no longer allowed. This includes types such as [Int!] and (Int!, Int!).
>>
>> The IUO attribute is not inferred from one declaration to another. For example, in the following code:
>>
>> let x: Int! = 5
>> let y = x
>> … x and y both have type Int?, not Int!, and y lacks the IUO attribute. This rule prevents IUO attributes from spreading via type inference.
>>
> I think that this statement will draw confusion in review, because “x” has IUO behavior. Perhaps you can talk about it in terms of type propagation and describe the behavior along the lines of:
>
> if the expression can be successfully type checked with the declaration producing a strong optional, it does. However, the type checker will fall back to trying to fall back to forcing the optional - if that succeeds it will. The end result of this is that the result of any rvalue that refers to something declared as an IUO will either have T or T? type. This means that in:
>
> let x: Int! = 5
> let y = x
> let z = x+0
>
> “x” is declared as an IUO, but because the initializer for y type checks correctly as an optional, y will be bound as type "Int?”. Since the initializer for z does not type check with x declared as an optional, the compiler forces the IUO and type checks the initializer as an Int.
>
> This model is more predictable, because IUOs are forced much more locally to where they are introduced into code, they do not propagate unpredictably through code. Any unpredictable propagation of an unknownable-null value is instead propagates as a strong optional, which is the safe default.
Thanks for the detailed feedback here. I’ve rewritten this section.
>
>
>> <https://github.com/cwillmor/swift-evolution/blob/89971a8162eba3aeb238d47772cda295a02cc585/proposals/0000-abolish-iuo.md#examples>Examples
>>
>> func f() -> Int! { return 3 } // f: () -> Int?, has IUO attribute
>> let x1 = f() // succeeds; x1: Int? == 3
>> let x2: Int? = f() // succeeds; x2: Int? = .Some(3)
> .some and .none are lower case these days :-)
So they are! Fixed.
>> <https://github.com/cwillmor/swift-evolution/blob/89971a8162eba3aeb238d47772cda295a02cc585/proposals/0000-abolish-iuo.md#impact-on-existing-code>Impact on existing code
>>
> I would add an intro paragraph/sentence saying that we do expect this to be a source breaking change, and thus it makes sense to do in Swift 3. We consider this to be acceptable because IUOs coming in through imported ObjC/C modules naturally “shimmer” in IUO’ness as nullability gets audited.
>
>> Variable bindings which previously had inferred type T! from their binding on the right-hand side will now have type T?. The compiler will emit an error at sites where those bound variables are used in a context that demands a non-optional type and suggest that the value be forced with the ! operator.
>>
>
> Overall, looks great, thank you for writing this up!
Thank you!
— Chris W.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160316/a8f7acbd/attachment.html>
More information about the swift-evolution
mailing list