[swift-evolution] Static Dispatch Pitfalls
michael.peternell at gmx.at
Sat May 21 16:54:38 CDT 2016
> Am 21.05.2016 um 23:22 schrieb Matthew Johnson via swift-evolution <swift-evolution at swift.org>:
> Sent from my iPad
> On May 21, 2016, at 3:16 PM, Brent Royal-Gordon <brent at architechies.com> wrote:
>>>> Where was proposed to force them to be final and was just trying to provide an example in which the conforming class may want to override them, so forcing them final isn't a good idea.
>>> Again, nobody ever proposed forcing them final. The proposal was to use final as a way to document the existing behavior.
>> I *did* propose forcing them final, and I'm still very skeptical that a `nondynamic` keyword that does nothing when you shadow the method is a good idea. People are still going to naïvely try to override these methods and be surprised when it doesn't work. A `nondynamic` keyword at the original declaration site will help them understand what happened when they're investigating the bug, but it still seems like this kind of code is so suspect that Swift ought to flag it from the start.
> Sorry about that. Either I didn't see that or I forgot about it. Making them 'final' causes problems with retroactive modeling. There are other issues as well but that is the most significant one.
indeed. IMHO a proper solution should deal with these use cases properly:
1) Someone adds a method to a class, and there are protocol extensions somewhere out there (maybe in another module) that he doesn't know about.
2) Someone creates a protocol extension for a type X, but he doesn't know the names of all (current and future) methods from all subtypes of X. How can this poor developer ever create a safe protocol extension?
This should not lead to
A) the class breaking (e.g. stopping to compile), because someone else creates a protocol extension with a conflicting symbol.
B) the wrong method being dispatched, because the two authors didn't agree on what the "makeBlue" method should do. they disagree, because they don't know each other. This becomes especially bad if both methods are not well-documented, and the contract mismatch is not obvious.
Can we agree that two methods with the same name sometimes have the same contract and sometimes not? And that this is not a programmer error? And that it would be good to distinguish between these two cases?
The more I think about it and follow the discussion, the more I come to the conclusion that the current behavior is not that bad. At least it is safe. Dispatching everything dynamically is unsafe (1). Adding a `nondynamic` keyword is unsafe (2). Forcing a `final` keyword is unsafe (3).
(1) I wrote about that earlier (yesterday I think)
(2) Because you would usually just rename such a method. It's much better. The problem becomes apparent when the class author doesn't know the protocol extension, or when the protocol extension is created later, maybe by a different author in a different module.
(3) This disallows methods with the same name in classes that fall into the scope of the extension. See (2).
More information about the swift-evolution