[swift-evolution] Pitch: really_is and really_as operators

Joe Groff jgroff at apple.com
Mon Sep 12 16:01:54 CDT 2016


> On Sep 12, 2016, at 12:24 PM, Paul Cantrell <cantrell at pobox.com> wrote:
> 
> 
>> On Aug 29, 2016, at 11:14 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>>> On Aug 24, 2016, at 5:08 PM, Charles Srstka via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> PROPOSED SOLUTION:
>>> 
>>> I propose the following operators: really_is, really_as, really_as?, and really_as!. These operators would only return a positive result if the type actually was what was being asked for, instead of something that might be able to bridge to that type.
>>> 
>>> DETAILED DESIGN:
>>> 
>>> let foo: Any = "Foo"
>>> let bar: Any = NSString(string: "Bar")
>>> 
>>> let fooIsString = foo is String                  // true
>>> let fooReallyIsString = foo really_is String     // true
>>> 
>>> let fooIsNSString = foo is NSString              // true
>>> let fooReallyIsNSString = foo really_is NSString // false
>>> 
>>> let barIsString = bar is String                  // true
>>> let barReallyIsString = bar really_is String     // false
>>> 
>>> let barIsNSString = bar is NSString              // true
>>> let barReallyIsNSString = bar really_is NSString // true
>>> 
>>> ALTERNATIVES CONSIDERED:
>>> 
>>> Stick with using an unholy combination of Mirror and unsafeBitCast when you need to know what you’ve actually got.
>> 
>> It would be helpful to know why you want this. What are you trying to do?
> 
> I’ve got one:
> 
> Siesta has a notion of “observer ownership,” whose semantics in a nutshell are “free the observer when its owners are all deallocated.” (Details here: http://bustoutsolutions.github.io/siesta/guide/memory/)
> 
> Never mind the details. The important thing is that owners must be objects because we care about the fact that they have an allocation lifecycle.
> 
> In Swift 2, this declaration ensured that callers used only objects as owners:
> 
> 	func addObserver(observer: ResourceObserver, owner: AnyObject)
> 
> In Swift 3, however, an unsuspecting called can pass a struct as an owner. Swift helpfully wraps it in a _SwiftValue, the _SwiftValue is only weakly referenced so it’s immediately deallocated, and so the observer is immediately discarded. It’s nonsensical. The compiler should be able to detect & prevent this.
> 
> What I want is:
> 
> 	func addObserver(observer: ResourceObserver, owner: AnyObjectForRealNotJustAValueWrapper)
> 
> AFAIK, this is impossible in Swift 3. Or is it?

If you declare the API as taking AnyObject in Swift, this should work *better* in Swift 3, since it is no longer possible to pass non-object value types to an AnyObject API by implicit conversion. If the API came from Objective-C, and uses `id` there, you could perhaps hide the `Any` version that gets imported and drop an AnyObject-taking version on top of it in a Swift overlay. I agree that we ought to have a more general feature in ObjC to say "no, really, this needs to be a reference type", but I think that's orthogonal to Charles' original request.

-Joe



More information about the swift-evolution mailing list