[swift-evolution] [Pitch] Overridable Members in Extensions
jordan_rose at apple.com
Wed Feb 10 21:57:35 CST 2016
> On Feb 10, 2016, at 18:29 , Greg Parker <gparker at apple.com> wrote:
>> On Feb 10, 2016, at 5:45 PM, Jordan Rose via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> Hey, everyone. Here's a small feature with ABI implications, ready for feedback. In addition to comments on the proposal itself, I'm also interested in hearing how often this comes up for people:
>> - extending a class you don't own
>> - to add an overridable method
>> - where some of the overriders might be outside the current module
>> https://github.com/jrose-apple/swift-evolution/blob/overridable-members-in-extensions/proposals/nnnn-overridable-members-in-extensions.md <https://github.com/jrose-apple/swift-evolution/blob/overridable-members-in-extensions/proposals/nnnn-overridable-members-in-extensions.md>
>> Overridable Members in Extensions
>> <https://github.com/jrose-apple/swift-evolution/tree/overridable-members-in-extensions#library-evolution>Library Evolution
>> As with any other method <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#classes>, it is legal to "move" an extension method up to an extension on the base class, as long as the original declaration is not removed entirely. The new entry point will forward over to the original entry point in order to preserve binary compatibility.
> What happens if the base class adds an independent implementation of the same method?
If it's an @objc method, you're hosed, just like you always were, but at least you'll (probably) find out when you recompile. I don't think there's anything we can do about this other than banning @objc methods in extensions, and I don't think that'll fly.
If it's a Swift method, it's not the "same" method; it's just another method with the same full-name. Existing binaries won't conflict. When you recompile, though, you'll get a conflict, and we don't currently have any annotations that allow you to fix that conflict, or for subclasses in a client module to deal with the intermediate module not yet having fixed the conflict. This isn't specific to extensions, though; you have the same problem with methods declared in the class body.
>> <https://github.com/jrose-apple/swift-evolution/tree/overridable-members-in-extensions#future-extensions>Future extensions
>> The restriction that an extension cannot override a method from another module is intended for safety purposes, preventing two modules from each adding their own override. It's possible to make this a link-time failure rather than a compile-time failure by emitting a dummy symbol representing the (class, member) pair.
> Dummy symbol enforcement only helps when two conflicting modules have a linkage relationship (i.e. one links to the other). It won't catch the case where two independent modules collide.
If two linker modules provide the same public symbol, that won't cause an issue?
(On the other hand, maybe we don't want to be producing extra public symbols just to check if someone made a mistake.)
> The old ObjC "qualified selectors" proposal handled a similar situation by mangling the original provider of the overridable method into the method name. This makes evolution trickier (you need to preserve the same mangled name even if the method moves into the base class or into a different module). On the plus side it allows independent extensions and subclasses to do independent things. It also preserves binary compatibility of those extensions and subclasses if the base class adds its own unrelated method with the same name. (Source compatibility in that case is not preserved. The extensions and subclasses would need to add further annotations to preserve their independence when recompiled.)
Yep, that's pretty much what the Swift implementation strategy is. I think my paragraph above is basically a rewrite of this.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution