[swift-evolution] [Pitch] Reducing the bridging magic in dynamic casts

Joe Groff jgroff at apple.com
Mon May 2 17:53:06 CDT 2016


> On May 2, 2016, at 3:50 PM, Chris Lattner <clattner at apple.com> wrote:
> 
> 
>> On May 2, 2016, at 3:43 PM, Joe Groff <jgroff at apple.com> wrote:
>> 
>> 
>>> On May 2, 2016, at 2:45 PM, Chris Lattner <clattner at apple.com> wrote:
>>> 
>>> On Apr 29, 2016, at 3:00 PM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>>>> I’d like to propose the following changes:
>>>> 
>>>> 	• Dynamic casts as?, as! and is should no longer perform bridging conversions between value types and Cocoa classes.
>>>> 	• Coercion syntax as should no longer be used to explicitly force certain bridging conversions.
>>>> 	• To replace this functionality, we should add initializers to bridged value types and classes that perform the value-preserving bridging operations.
>>> +1.  I think that this will lead to a much cleaner and more predictable set of rules.  It will probably also define away a ton of bugs in the compiler and runtime.
>>> 
>>> 
>>> 
>>>> NSError bridging can also be extracted from the runtime, and the same functionality exposed as a factory initializer on NSError:
>>>> 
>>> I think that this proposal is overall really great, but what does it do to the “catch let x as NSError” pattern?  What is the replacement?  If the result is ugly, we may have to subset out NSError out of this pass, and handle it specifically with improvements to the error bridging story.
>>> 
>> 
>> If we remove the bridging magic and do nothing else, then the best you can do to catch any error and handle it as an NSError becomes a two-liner:
>> 
>> 	do {
>> 	  try something()
>> 	} catch let error {
>> 	  let nsError = NSError(error)
>> 	  handle(nsError)
>> 	}
>> 
>> That's definitely uglier, but just to play devil's advocate, this does have the benefit of making it much clearer that the 'catch' is exhaustive. 'as' patterns are usually refutable, and it's a weird exception that 'error as NSError' is an exhaustive match (and we do have bugs where we get this wrong, especially inside closures when we haven't fully propagated contextual types yet).
> 
> Right, that’s what I expected.  The problem here is that this is a super common pattern.  The solution to this is pretty straight-forward though: we should just make the most commonly used members of NSError be a protocol extension on ErrorProtocol (née ErrorType).  This would eliminate the most common reasons that people need this pattern.  Do you know of any issues with this, or are we merely a proposal away from making this happen?

I can't think of any problems that would block us from doing that today. It'd be pretty easy to write an ErrorProtocol extension that just forwards NSError's interface via bridging, and I bet that'd cover most use cases for 'as NSError':

extension ErrorProtocol {
  var domain: String { return NSError(self).domain }
  var code: Int { return NSError(self).code }
  var userInfo: [String: AnyObject] { return NSError(self).userInfo }
  /* etc. */
}

-Joe


More information about the swift-evolution mailing list