> On Mar 22, 2017, at 10:55 PM, Brent Royal-Gordon via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> On Mar 21, 2017, at 11:03 PM, Chris Lattner via swift-evolution 
>> <swift-evolution@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,

We can avoid these by migrating conservatively (have the migrator add @objc 
everywhere it’s inferred in Swift 3).

> and undetectable mistakes are going to continue on an ongoing basis. 

… but what you say above is definitely true: the error of omission of @objc 
will cause breakage for these cases. 


> 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.)

(Slava talked through some of these)

> Have you evaluated applying different rules to methods and properties?

For me, I’d rather reject the proposal as a whole than further complicate the 
rules for @objc inference.

> Have you considered a deprecation cycle (for instance, having Swift 4 thunks 
> log a warning that they're going away in Swift 5)?

I think Swift 3 -> Swift 4 is the deprecation cycle, no?

> Or is the real motivation that, code size issues aside, you think these 
> members ought to be explicitly marked `@objc` for philosophical reasons?

That’s certainly *a* reason. The @objc inference rules are fairly complicated 
and even experienced developers can’t easily guess whether something will be 
exposed to Objective-C or not because (e.g.) minor changes in the 
parameter/result types of a method can affect it.

> If so, how many times do you want people to say so?

Once per API that’s exposed to Objective-C.

> You already have to explicitly inherit from an `@objc` base class;

You don’t *need* to inherit from an `@objc` base class to have an @objc member, 
but @objc inference ties together the notions of 

Plus, inheritance from an Objective-C class is often incidental: you do it 
because you need an NSObjectProtocol conformance, or something else expects 
NSObject. I haven’t heard of developers inheriting from NSObject solely to get 
@objc inference for their members.

> you already have to specify `dynamic` to avoid optimizations;

Conceptually, ‘dynamic’ is orthogonal to ‘@objc’. In today’s implementation, we 
can only implement ‘dynamic’ via the Objective-C runtime, hence this proposal’s 
requirement to write both.

> 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?

There probably are; making an Int parameter of a final method Int? isn’t 
generally source-breaking, but means that you can no longer expose an @objc 
entrypoint. That said...

> Or can you just deprecate the `@objc` version and move on?

it’s easy to leave a deprecated @objc entrypoint in place if this happened to 
you, so I don’t think “accidentally made an @objc API that I wanted to be 
@nonobjc and now I have to support it going forward” is  strong argument in 
favor of this proposal.

        - Doug

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to