I think limiting to types that are both @objc and RawRepresentable is a nice compromise; that limits the type preservation needed to work around "slushiness" to NSString, NSNumber (already done), and NSError.
I know your pitch doesn't cover this problem, but I would also note that C varargs suffer from the same "needing to know to get the rawValue" problem. Sincerely, Zachary Waldowski [email protected] On Thu, Sep 29, 2016, at 10:16 AM, Joe Groff via swift-evolution wrote: > In the discussion around SE-0139 (bridging NSNumber and NSValue), many > people pointed out that it's common in ObjC to use NSNumbers holding enum > constants in Cocoa containers. Many ObjC interfaces look something like > this: > > /// A washing machine. > @interface QXWashingMachine > > /// Wash cycles supported by the washing machine. > typedef NS_ENUM(NSInteger, QXWashCycle) { > QXWashNormal, > QXWashDelicates, > QXWashLinens, > }; > > /// Perform a sequence of wash cycles. Takes an NSArray of QXWashCycle > constants passed > /// as NSNumbers. > - (void)performWashCycles:(NSArray *)cycles; > > @end > > In ObjC, you can call this API like this: > > [washingMachine performWashCycles:@[ > @(QXWashLinens), > @(QXWashDelicates), > ]]; > > In Swift 3, the equivalent code will compile, but fail at runtime, > because the enum type falls back to opaque object bridging instead of > using NSNumbers: > > // Fails at runtime, because WashCycle constants don't implicitly > bridge to NSNumber > washingMachine.perform(washCycles: [WashCycle.linens, > WashCycle.delicates]) > > so you have to know to get the `rawValue`s out first: > > // Fails at runtime, because WashCycle constants don't implicitly > bridge to NSNumber > washingMachine.perform(washCycles: [WashCycle.linens.rawValue, > WashCycle.delicates.rawValue]) > > We encountered similar problems last year as we developed the > `swift_newtype` ObjC feature last year, which enabled us to import some > stringly-typed ObjC APIs with stronger types in Swift. A type like > `Notification.Name`, which represents a set of NSString constants, is > imported to be RawRepresentable as String and also to bridge to > Objective-C as one, by having the compiler implicitly generate a > conformance to the internal _ObjectiveCBridgeable protocol for it. We > could conceivably do one of the following things: > > - Have the compiler generate a bridging conformance for imported NS_ENUM > and NS_OPTIONS types, and perhaps also for @objc enums defined in Swift, > like we do for newtypes. > - Alternatively, we could say that *anything* with a RawRepresentable > conformance bridges to ObjC as its rawValue. > > The second one is conceptually appealing to me, since RawRepresentable is > already something newtypes, enums, and option sets have in common in > Swift, but I think it may be too lax—it would effectively make > RawRepresentable the user interface to Objective-C bridging, which I'm > not sure is something we want. Limiting the bridging behavior to @objc > enums and imported option sets limits the impact, though there are still > tradeoffs to consider: > > - Adding any new bridging behavior has the potential to break existing > code that relies on the current opaque object bridging. We tell people > not to do that, of course, but that's no guarantee that people don't. > - As with newtypes, the bridged Objective-C representation loses type > information from Swift, meaning that dynamic casts potentially need to > become "slushier". Swift maintains the distinction between > Notification.Name and String, for example, but once a value of either > type has been bridged to NSString, the distinction is lost, so we have to > allow casts from NSString back to either String or Notification.Name. If > we bridge enums and option sets, we would similarly lose type information > once we go to NSNumber. We can in some cases mitigate this for class > clusters like NSString or NSNumber by using our own subclasses that > preserve type info, which can at least preserve type info for > Swift-bridged objects, though we can't do this universally for all > Cocoa-sourced objects. > > -Joe > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
