[swift-evolution] [Review] SE-0160: Limiting @objc inference

Brent Royal-Gordon brent at architechies.com
Thu Mar 23 00:55:06 CDT 2017

> On Mar 21, 2017, at 11:03 PM, Chris Lattner via swift-evolution <swift-evolution at swift.org> wrote:
> * What is your evaluation of the proposal?

I'm going to have to come down on the "no" side on this one.

I'm actually not worried about methods so much as properties. KVC is completely untyped on the Objective-C side, and there are several different mechanisms there which use KVC with poorly validated external strings, like bindings, sort descriptors, and predicates. Tons of migration errors are going to escape into production if we do this, and undetectable mistakes are going to continue on an ongoing basis. 

Have we explored alternate implementations? For instance, when the compiler can statically determine all of the call sites for an `@objc` member, could we emit *only* an implementation with the Objective-C calling convention and call that directly from Swift?

Could members with binary-compatible signatures share a thunk? The Objective-C calling convention includes a selector parameter, so you can still determine the desired message.

Could we give implicit methods and properties a different, slower implementation that leverages Objective-C's dynamic features? Imagine, for instance, mapping in `imp_implementationWithBlock()`-style pages of general-purpose thunks at runtime to reduce code size, then installing them lazily with `+resolveClassMethod:`. (Maybe this could actually be made fast enough, amortized over all calls, that we could get rid of the thunks entirely—I don't know.)

Have you evaluated applying different rules to methods and properties? Have you considered a deprecation cycle (for instance, having Swift 4 thunks log a warning that they're going away in Swift 5)?

Or is the real motivation that, code size issues aside, you think these members ought to be explicitly marked `@objc` for philosophical reasons? If so, how many times do you want people to say so? You already have to explicitly inherit from an `@objc` base class; you already have to specify `dynamic` to avoid optimizations; now you also have to mark individual members `@objc`? Would you like the request for bridging notarized and filed in triplicate?

I can understand the impulse to require it explicitly on `public` members, but on the other hand, if you *do* accidentally publish a member as `@objc`, what's the harm? Is there any non-breaking change you can make to a `@nonobjc` method which wouldn't be legal on an `@objc` one? Or can you just deprecate the `@objc` version and move on?

Overall, I think this is far too bureaucratic, and I'm not convinced that either the technical or the theoretical justification is compelling. Maybe you've eliminated some of the possibilities I've suggested or there are negative effects I don't understand, but right now, I don't see it. 

> * Is the problem being addressed significant enough to warrant a change to Swift?

I'm uncertain. 

> * Does this proposal fit well with the feel and direction of Swift?

It fits with certain goals, like making public APIs explicit, but not with others, like avoiding boilerplate. 

> * If you have you used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I haven't used anything with such deep foreign-language bridging as Swift. 

> * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick reading during a hockey game, so please forgive any oversights. 

Sent from my iPad

More information about the swift-evolution mailing list