[swift-evolution] [Draft] Abolish IUO type

Chris Willmore cwillmore at apple.com
Wed Mar 16 23:16:14 CDT 2016


> On Mar 16, 2016, at 5:27 PM, Mark Anders <mark at markanders.net> wrote:
> 
> It seems reasonable.  If I understand it correctly, I would still be able to write code like this:
> 
>     @IBOutlet weak var emailTextField: UITextField!

That’s correct (and IBOutlets remain a compelling use case for IUOs until we have a better story for deferred initialization).
> 
> I don’t have any issues with the limitations as proposed.
> 
> Btw, I included the above line because with all of the examples you used, IMO, it can be easy to question how important IUO are.  I’ve never needed [Int!], for example or relied on the compiler inferring that something is implicitly unwrapped.  
> 
> However I have a ton of code like the line above, and  it would be a drag if these all became optionals.  I wouldn’t want to have to if let or guard let for every property in every function where they are used.  

To run with the example above, emailTextField would have type UITextField? but, because it’s an IUO declaration, it would still be usable in contexts that required non-optional UITextField. What would change is that if you were to say, e.g.

let textField = controller.emailTextField

then textField would have type UITextField?. But you could still say

formView.addSubview(controller.emailTextField)

without having to force emailTextField. The type checker recognizes that emailTextField is an IUO property and allows it to be implicitly forced to satisfy the non-optional parameter type UIView of UIView.addSubview.
> 
> In general where I find myself using them the most is in situations where the initialization patterns don’t apply.  Another example is in unit tests where you want to tear down and rebuild but not necessarily re-construct.  These might fall in to the category of where you might “introduce more specific language features to take their place”, but since there’s no mention of what those might be, it’s hard to know what one is getting to replace what one’s giving up.
> 
> Finally, I really don’t like @implicitly_unwrapped. 
> 
>     @IBOutlet @implicitly_unwrapped weak var emailTextField: UITextField?
>     @IBOutlet @implicitly_unwrapped weak var passwordTextField: UITextField?
>     @IBOutlet @implicitly_unwrapped weak var loginButton: UIButton?
> 
> Making things really ugly isn’t going to discourage me from using them in situations like this and I think it makes me more aware of the danger involved.  It just makes it harder to read, IMO.

Sorry, I should have made it clear that I’m not suggesting it be spelled @implicitly_unwrapped; you’re right that it’s ugly. I was more suggesting that maybe in the future it should be syntactically similar to other decl attributes. But that’s out of scope for this proposal. 

Thanks for the feedback!
— Chris Willmore
> 
> Mark
> 
> On March 15, 2016 at 10:03:24 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>
>> 
>> Thanks,
>> — Chris Willmore
>> 
>> 
>> Abolish ImplicitlyUnwrappedOptional type
>> 
>> Proposal: SE-NNNN
>> Author: Chris Willmore <http://github.com/cwillmor>
>> Status: TBD
>> Review Manager: TBD
>> This proposal seeks to remove the ImplicitlyUnwrappedOptional type from the Swift type system and replace it with an IUO attribute on declarations. Appending ! to the type of a Swift declaration will give it optional type and annotate the declaration with an attribute stating that it (or, in the case of a function, the return value of its application) may be implicitly unwrapped.
>> 
>>  <https://github.com/cwillmor/swift-evolution/blob/89971a8162eba3aeb238d47772cda295a02cc585/proposals/0000-abolish-iuo.md#motivation>Motivation
>> 
>> The ImplicitlyUnwrappedOptional ("IUO") type is a valuable tool for importing Objective-C APIs where the nullability of a parameter or return type is unspecified. It also represents a convenient mechanism for working through definite initialization problems in initializers. However, IUOs are a transitional technology; they represent an easy way to work around un-annotated APIs, or the lack of language features that could more elegantly handle certain patterns of code. As such, we would like to limit their usage moving forward, and introduce more specific language features to take their place. Except for a few specific scenarios, optionals are always the safer bet, and we’d like to encourage people to use them instead of IUOs.
>> 
>> This proposal seeks to limit the adoption of IUOs to places where they are actually required, and put the Swift language on the path to removing implicitly unwrapped optionals from the system entirely when other technologies render them unnecessary. It also completely abolishes any notion of IUOs below the type-checker level of the compiler, which will substantially simplify the compiler implementation.
>> 
>>  <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
>> Declarations that are marked with the IUO attribute 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.
>> 
>> 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.
>> 
>> 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.
>> 
>> A variable with the IUO attribute may still be converted to a value with non-optional type, through either evaluating it in a context which requires the non-optional type, explicitly converting it to a non-optional type using the as operator, binding it to a variable with explicit optional type, or using the force operator (!).
>> 
>>  <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)
>> let x3: Int! = f() // succeeds; x3: Int? = .Some(3), has IUO attribute
>> let x4: Int = f() // succeeds; x4: Int = 3
>> let a1 = [f()] // succeeds; a: [Int?] = [.Some(3)]
>> let a2: [Int!] = [f()] // illegal, nested IUO type
>> let a3: [Int] = [f()] // succeeds; a: [Int] = [3]
>> 
>> func g() -> Int! { return nil } // f: () -> Int?, has IUO attribute
>> let y1 = g() // succeeds; y1: Int? = .None
>> let y2: Int? = g() // succeeds; y2: Int? = .None
>> let y3: Int! = g() // succeeds; y3: Int? = .None, has IUO attribute
>> let y4: Int = g() // traps
>> let b1 = [g()] // succeeds; b: [Int?] = [.None]
>> let b2: [Int!] = [g()] // illegal, nested IUO type
>> let b3: [Int] = [g()] // traps
>> 
>> func p<T>(x: T) { print(x) }
>> p(f()) // prints "Optional(3)"; p is instantiated with T = Int?
>> 
>> if let x5 = f() {
>>   // executes, with x4: Int = 3
>> }
>> if let y5 = g() {
>>   // does not execute
>> }
>>  <https://github.com/cwillmor/swift-evolution/blob/89971a8162eba3aeb238d47772cda295a02cc585/proposals/0000-abolish-iuo.md#impact-on-existing-code>Impact on existing code
>> 
>> 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.
>> 
>> Explicitly written nested IUO types (like [Int!]) will have to be rewritten to use the corresponding optional type ([Int?]) or non-optional type ([Int]) depending on what's more appropriate for the context. However, most declarations with non-nested IUO type will continue to work as they did before.
>> 
>> It will still be possible to declare IUO properties, so the following deferred initialization pattern will still be possible:
>> 
>> struct S {
>>   var x: Int!
>>   init() {}
>>   func initLater(x someX: Int) { x = someX }
>> }
>>  <https://github.com/cwillmor/swift-evolution/blob/89971a8162eba3aeb238d47772cda295a02cc585/proposals/0000-abolish-iuo.md#future-directions>Future directions
>> 
>> Because this proposal changes the IUO-ness of a declaration from being part of its type to being an attribute of the declaration, it might make sense to changes the syntactic representation of the attribute to match, e.g. by creating a new @implicitly_unwrapped attribute on declarations:
>> 
>> let x3: Int! = f() // !-based syntax
>> @implicitly_unwrapped let x3: Int? = f() // attribute-based syntax
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160316/d31e648d/attachment.html>


More information about the swift-evolution mailing list