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