> Please no. Just because I have to subclass NSObject doesn't mean I want to > discard the performance benefits of static dispatch, and it especially > doesn't mean I want to actually change the semantics of method resolution. > Taking an existing Swift class and changing its base class to NSObject should > not change how its methods are dispatched.
Subclassing NSObject already changes how dispatch happens. NSObject extensions will use message dispatch for instance. I really don't think that table -> message dispatch will result in a real life performance impact, but I agree that consistency is valuable. The static dispatch upgrade loss is disappointing. In practice however, I don't think that this has ever had an impact on my code. If performance is a consideration, most people just drop NSObject. If you are using NSObject, you are probably using it because of a large objective-c code base, in which case, I don't think the profiler is really going to notice the few statically dispatched functions. > Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. In > Obj-C it's ad-hoc, many classes support it for properties but many also > don't, and very few properties have their KVO conformance documented. I don't > view having to mark my properties as `dynamic` to participate in KVO to be a > problem with Swift but rather a feature. It tells the reader that this > property supports KVO. This is an interesting point, and it would be an interesting semantic. However in practice, the majority of NSObject code is imported from obj-c, and it's generated interface does not follow this convention. Also, it's strange to conflate how something was dispatched and if it supported KVO. I think property delegates will be the future here and enable some exciting contracts if adopted. Another approach is to just make it easier to opt into the full obj-c machinery. The addition of a class or extension level `dynamic` keyword would be great. If we could get buy in on this, then the debate becomes if NSObject should default to `dynamic` or not. Brian > > -Kevin Ballard > > On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote: >> I wanted to follow up to a blog post I wrote about Message Dispatch in >> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I >> mentioned some changes to NSObject that didn’t result in any >> objections, so I thought it was time to see what the SE mailing list >> thought. >> >> I’ve read a few conversations on SE mailing list that have morphed >> into abstract conversations about dynamic vs static dispatch. I want >> to focus specifically on how Swift NSObject subclasses behave. >> >> I think that there are 2 changes that will result in fewer bugs and >> will not have a substantial impact on performance: >> >> >> ## Remove Table Dispatch from NSObject >> >> NSObject subclasses use table dispatch for the initial class >> declaration block. I think that using message dispatch for NSObject >> subclasses everywhere will result in a much more consistent developer >> experience. >> >> ## Block NSObject Visibility Optimizations >> >> Swift upgrades method dispatch to final when the compiler can prove >> that the method is not subclassed. I would like to see Swift be more >> careful about the impact of these optimizations on message dispatch, >> and consider message dispatch non-upgradable. >> >> >> I thought it would help to frame this choice as a trade-off between >> Swift’s goals of safe, fast, and expressive. >> >> ## Safe >> >> Always using message dispatch for NSObject subclasses will fix a class >> of runtime errors in framework features that are designed around >> message passing (e.g. KVO). Arguments against using dynamic features >> like this are valid, but Cocoa frameworks still use dynamic features >> and the above behaviors result in actual bugs. As a bonus, this will >> resolve SR-584, where a table-dispatched method that is overridden by >> a message dispatch method doesn’t behave correctly. >> >> ## Fast >> >> The above changes will result in slower dispatch in NSObject >> subclasses. However, I don't think that these dispatch changes >> actually have a tangible impact on performance. Most NSObject >> subclasses sit on top of a lot of `objc_msgSend`, and if there is a >> specific hot spot, it would still be optimizable via the final >> keyword. >> >> ## Expressive >> >> Using table dispatch for NSObject without any source indication or >> library documentation is not very expressive. I think it’s important >> to weigh table dispatch behavior against all of the framework >> documentation and developer experience that assume message dispatch. >> This will also eliminate the need for a lot of `@objc` and `dynamic` >> annotations that are often inconsistently applied depending on if they >> are needed in the scope they are defined in (e.g. class vs extension). >> >> >> If this idea shows promise, I’d be glad to formalize a Swift Evolution >> Proposal and explore syntactic details. I think being able to flag a >> class with `dynamic` and applying this flag to `NSObject` may be the >> only syntactic change needed. However, it would be good to debate the >> merit of the behavior change before the syntax. >> >> >> Thanks! >> >> >> Brian King >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution