[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