Hello Swift community,
The review of SE-0140 <https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md> "Bridge Optional As Its Payload Or NSNull” ran from September 2…8, 2016. The proposal is accepted with one modification (described below).
Reviews on this proposal were mixed, with many expressing significant concerns about the ability to place an optional value into an ‘Any’, particularly when the ‘Any’ comes from a nonnull-annotated Objective-C API:
@interface MyClass : NSObject
- (void)doSomething:(nonnull id)object;
let stringOpt: String? = getSomeString()
MyClass().doSomething(stringOpt) // allowed; likely a programmer error
This behavior was introduced as part of id-as-Any bridging (SE-0116 <https://github.com/apple/swift-evolution/blob/master/proposals/0116-id-as-any.md>). As an amendment to SE-0140, Swift will produce a warning when an optional value is converted to a value of type Any, e.g.,
MyClass().doSomething(stringOpt) // warning: optional value of type ‘String?’ is converted to an ‘Any’
// note: use ‘!’ to force-unwrap the optional
// note: use ‘??’ to provide a default value if the optional is nil
// note: use ‘as Any’ to silence this warning
Such a warning will address most accidental injections of optional values into Any, and the core team felt that this addresses accidental boxing of optional values better than leaving the opaque object types to fail fast in Objective-C code that inspects them (e.g., see this message <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160905/026961.html> for a negative review partly on these grounds).
To the main point of this proposal, which is to bridging to either the payload or NSNull, the core team felt that:
1) Bridging to the payload or NSNull brings to Objective-C code the same behavior that is already present in Swift’s type system, where an optional containing a payload can be dynamically casted to its payload type. For example, this is well-formed in Swift:
let optString: String? = "hello"
let anyValue: Any = optString
let stringValue: String = any as! stringValue // downcast succeeds, produces a String
2) While NSNull is not widely used in Cocoa APIs, it is better to enable those APIs to work properly when nil optional values do get bridged than to have an opaque-to-Objective-C boxed type that does not work well with any Objective-C APIs.
Thank you to everyone who participated in the review!