[swift-evolution] [Proposal] Remove behavior on AnyObject that allows any obj-c method to be called on it

Chris Lattner clattner at apple.com
Mon Apr 18 22:47:17 CDT 2016


+1 for using a non implicit optional type.

-Chris

> On Apr 18, 2016, at 8:01 PM, Joe Pamer via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Just an update on this… (Sorry about the delay!)
> 
> After experimenting with the changes outlined below, and discussing the matter with a few folks off-list, it seems like a better compromise would be to only adopt option #2. We would keep the direct member access syntax and wrap the results of any dynamic member access expressions in an Optional, as opposed to an IUO. In practice this feels like a nice compromise that will prevent many users from shooting themselves in the foot, as changing the wrapping to optional forces users to immediately account for failures without having to jump through too many hoops.
> 
> Thoughts?
> 
> Thanks!
> - Joe
> 
>>> On Mar 23, 2016, at 12:45 PM, Joseph Pamer <jpamer at apple.com> wrote:
>>> 
>>> 
>>> On Mar 23, 2016, at 11:29 AM, Jordan Rose <jordan_rose at apple.com> wrote:
>>> 
>>> The most common use case I've seen for this has been drilling into a heterogeneous collection without specifying intermediate types, i.e. `pluginProperties["actions"][0]["name"]`. Some possible variations on this proposal could continue to allow that:
>>> 
>>> - Remove all lookup except the subscripts `(AnyObject) -> AnyObject?` and `(Int) -> AnyObject`.
>>> - Instead of removing AnyObject lookup completely (the proposal), change the IUO-wrapped results (the current behavior) to use Optional, requiring developers to explicitly deal with the possibility of failure.
>>> - Both of the above.
>>> 
>>> I know Joe Pamer has been looking into seeing how this feature is used by introducing a warning for it in the type checker. Before making any changes here we'd want to know how it affects real-world projects.
>> 
>> I should be pushing a branch that does both of the above “real soon now”. (This branch also includes my recent experiments in inhibiting implicit bridging conversions.) I’ll be curious to know what people think once they’ve had a chance to play with these changes.
>> 
>> Thanks!
>> - Joe
>> 
>>> 
>>> Jordan
>>> 
>>> 
>>>> On Mar 22, 2016, at 18:59 , Kevin Lundberg via swift-evolution <swift-evolution at swift.org> wrote:
>>>> 
>>>> In "Using Swift with Cocoa and Objective-C", this behavior is described as part of how AnyObject works:
>>>> 
>>>> “You can also call any Objective-C method and access any property without casting to a more specific class type." … "However, because the specific type of an object typed as AnyObject is not known until runtime, it is possible to inadvertently write unsafe code. As in Objective-C, if you invoke a method or access a property that does not exist on an AnyObject typed object, it is a runtime error.”
>>>> 
>>>> I propose that we remove this behavior entirely to push swift further in the direction of type safety.
>>>> 
>>>> Rationale:
>>>> Even if you don’t mean to write code that relies on this behavior, it's easy to accidentally do so when interfacing with various Cocoa APIs due to type inference. A developer may not even realize that their code is unsafe since their code will compile just fine when calling obj-c visible methods. Removing this behavior would alleviate any confusion that a developer may have while writing this, especially as it is not a highly advertised feature of AnyObject. Furthermore, anyone who reads swift code using this will know with more certainty what types the author expects to be using here since an explicit cast will be required.
>>>> 
>>>> Considerations:
>>>> If this is done, the way I see AnyObject behaving is similar to Any, where you need to manually downcast in order to call methods on things. Code would change from this:
>>>> 
>>>> 
>>>> class Foo: NSObject { func bar() {} }
>>>> let things = NSOrderedSet(object: Foo())
>>>> 
>>>> for thing in things { // thing is AnyObject
>>>> 	thing.bar() // happens to work but not verified by compiler, may crash in the future
>>>> }
>>>> 
>>>> 
>>>> to something like this:
>>>> 
>>>> //...
>>>> 
>>>> for thing in things {
>>>> 	if let foo = thing as? Foo { // needs an explicit cast
>>>> 		foo.bar() // type checked, verified by compiler, won’t crash due to missing method
>>>>         }
>>>> }
>>>> 
>>>> 
>>>> One ancillary benefit that I can see of doing this is that it could make AnyObject consistent across darwin and other platforms. As far as I can tell, this behavior only exists on platforms where swift integrates with the objective-c runtime, and doing this will help swift code be more portable as it doesn’t rely on this implicit behavior.
>>>> 
>>>> Any thoughts?
>>>> 
>>>> --
>>>> Kevin Lundberg
>>>> kevin at klundberg.com
>>>> 
>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160418/bf36d8e3/attachment.html>


More information about the swift-evolution mailing list