> On Jan 6, 2017, at 3:46 AM, Rod Brown <[email protected]> wrote: > >> >> On 5 Jan 2017, at 11:50 am, Douglas Gregor via swift-evolution >> <[email protected] <mailto:[email protected]>> wrote: >> >> Hi all, >> >> Here’s a draft proposal to limit inference of @objc to only those places >> where we need it for consistency of the semantic model. It’s in the realm of >> things that isn’t *needed* for ABI stability, but if we’re going to make the >> source-breaking change here we’d much rather do it in the Swift 4 time-frame >> than later. Proposal is at: >> >> >> https://github.com/DougGregor/swift-evolution/blob/objc-inference/proposals/NNNN-objc-inference.md >> >> <https://github.com/DougGregor/swift-evolution/blob/objc-inference/proposals/NNNN-objc-inference.md> >> > >> >> <https://github.com/DougGregor/swift-evolution/tree/objc-inference#source-compatibility>Source >> compatibility >> >> The two changes that remove inference of @objc are both source-breaking in >> different ways. The dynamic change mostly straightforward: >> >> In Swift 4 mode, introduce an error that when a dynamic declaration does not >> explicitly state @objc, with a Fix-It to add the @objc. >> >> In Swift 3 compatibility mode, continue to infer @objc for dynamic methods. >> However, introduce a warning that such code will be ill-formed in Swift 4, >> along with a Fix-It to add the @objc. This >> >> A Swift 3-to-4 migrator could employ the same logic as Swift 3 compatibility >> mode to update dynamic declarations appropriately. >> >> The elimination of inference of @objc for declarations in NSObject >> subclasses is more complicated. Considering again the three cases: >> >> In Swift 4 mode, do not infer @objc for such declarations. Source-breaking >> changes that will be introduced include: >> >> If #selector or #keyPath refers to one such declaration, an error will be >> produced on previously-valid code that the declaration is not @objc. In most >> cases, a Fix-It will suggest the addition of @objc. >> >> The lack of @objc means that Objective-C code in mixed-source projects won't >> be able to call these declarations. Most problems caused by this will result >> in warnings or errors from the Objective-C compiler (due to unrecognized >> selectors), but some might only be detected at runtime. These latter cases >> will be hard-to-detect. >> >> Other tools and frameworks that rely on the presence of Objective-C >> entrypoints but do not make use of Swift's facilities for referring to them >> will fail. This case is particularly hard to diagnose well, and failures of >> this sort are likely to cause runtime failures that only the developer can >> diagnose and correct. >> >> In Swift 3 compatibility mode, continue to infer @objc for these >> declarations. When @objc is inferred based on this rule, modify the >> generated header (i.e., the header used by Objective-C code to call into >> Swift code) so that the declaration contains a "deprecated" attribute >> indicating that the Swift declaration should be explicitly marked with >> @objc. For example: >> >> class MyClass : NSObject { >> func foo() { } >> } >> will produce a generated header that includes: >> >> @interface MyClass : NSObject >> -(void)foo NS_DEPRECATED("MyClass.foo() requires an explicit `@objc` in >> Swift 4"); >> @end >> This way, any reference to that declaration from Objective-C code will >> produce a warning about the deprecation. Users can silence the warning by >> adding an explicit @objc. >> >> A Swift 3-to-4 migrator is the hardest part of the story. Ideally, the >> migrator to only add @objc in places where it is needed, so that we see some >> of the expected benefits of code-size reduction. However, there are two >> problems with doing so: >> >> Some of the uses that imply the need to add @objc come from Objective-C >> code, so a Swift 3-to-4 migrator would also need to compile the Objective-C >> code (possibly with a modified version of the Objective-C compiler) and >> match up the "deprecated" warnings mentioned in the Swift 3 compatibility >> mode bullet with Swift declarations. >> >> The migrator can't reason about dynamically-constructed selectors or the >> behavior of other tools that might directly use the Objective-C runtime, so >> failing to add a @objc will lead to migrated programs that compile but fail >> to execute correctly. >> >> > Yeah, this is definitely a point of concern. I’m not sure that the first part > deals with stuff like frameworks and libraries that currently expose > functionality to external users in Obj-C. How could you be sure which API was > designed to be used by Obj-C when it comes to libraries?
It is *very* hard to know. > As others have mentioned, perhaps we could have options in the converter? I’m > not generally a fan of this type of preference selection but in this case it > seems reasonable. Yeah, maybe. Designing the migrator itself isn’t really in the scope of the Swift evolution process, but we do appreciate hearing people’s ideas here. It’s a tough thing to migrate well. > The dynamically constructed selector case seems rare, especially considering > that using string-based selectors has been deprecated since Swift 2.2. I suspect that you are right that failures would be rare. It’s the >> >> <https://github.com/DougGregor/swift-evolution/tree/objc-inference#overriding-of-declarations-introduced-in-class-extensions>Overriding >> of declarations introduced in class extensions >> >> There are several potential solutions to this problem, but both are >> out-of-scope for this particular proposal: >> >> Require that a non-@objc declaration in a class extension by explicitly >> declared final so that it is clear from the source that this declaration >> cannot be overridden. >> >> Extend Swift's class model to permit overriding of declarations introduced >> in extensions. >> >> > I will definitely be running into this issue if/when this occurs. A lot of > users use extensions to break up their code into clear elements for > organisational reasons, and also adding functionality to external libraries. > Both here would end up with odd behaviour and I really hope we go with Option > 2 here. Either option requires a proposal; Option 2 can certainly have ABI impact because it could effect the ABI of Swift classes. As an aside, we/I realized belatedly that this proposal obviously doesn’t fit Swift 4 stage 1, so we’ll hold off on the review until we open up stage 2. - Doug
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
