[swift-evolution] [Pitch] Changing NSObject dispatch behavior
kevin at sb.org
Wed Dec 14 17:58:42 CST 2016
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.
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.
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
> 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
> ## 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
> ## 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.
> Brian King
> swift-evolution mailing list
> swift-evolution at swift.org
More information about the swift-evolution