[swift-evolution] [Draft Proposal] Require `final` on protocol extension members
brent at architechies.com
Mon Jan 4 18:38:25 CST 2016
> Didn't we already have a very long discussion about all of this?
We did, which ended with you and I clearly in fundamental disagreement, while others appeared to think it was a good idea. I'm now putting forth a more specific version of that proposal, one that I think is almost ready for review.
> It's confusing, it's overloading the term `final` in a way that doesn't seem to make sense (`final` means you can't subclass or override, but there's nothing in this proposal that affects either subclassing _or_ method overriding)
`final` is currently restricted to the context of a class, yes. But I think it's a clean extension of the concept to use it to mark protocol extension methods that can't be overridden. Hence why I provide this re-definition of the meaning of `final`:
`final` declares that subtypes of this type must use this specific implementation of the member, and cannot substitute their own specialized implementation. Attempting to do so causes an error.
(Technically it's true that no protocol extension member can be overridden. But the distinction between defaulted protocol members and protocol extension members is very subtle—they are both written in protocol extensions and look identical unless you go back to the protocol definition to check what's there—and I think it needs to be called out in the text of the code.)
> and it means protocol extensions that you aren't even aware of from other modules can cause your otherwise-legal type to start throwing errors.
You can only get a conflict from something that's visible to your code. For instance, an `internal` protocol extension in another module can't cause a conflict—only public APIs can cause conflicts through imports. And it's important that they do, because it's hard to know that you didn't think the conflicting member was a defaulted protocol requirement you could override.
> Making this kind of change only makes any sense at all if you assume that, every single time someone implements a method that happens to look the same as a method provided by a protocol extension, they're trying to override that protocol extension method. But since protocol extension methods cannot be overridden (merely shadowed), that assumption doesn't make a lot of sense.
I realize that this doesn't confuse you, but it seems to confuse everyone else. The core team seems to think so too, because they consider the lack of a warning about it to be a bug that can be fixed without going through the evolution process. (And I believe there's a thread currently in swift-dev where someone is working on that warning.)
> and I think forcing people to brand their legitimate functions with a negative-sounding term "incoherent" is also basically subtly punishing people. I mean, who wants to write code that is publicly branded as being "incoherent" code?
"Incoherent" is a very opinionated keyword. But I think it's also a descriptive one, which captures in a single word why you may not want to use it. I'm open to alternatives, including less judgmental alternatives.
> Also, even after reading this proposal, it's still not obvious to me how the @incoherent attribute works. The rest is a little confusing, but this attribute is very confusing all by itself.
`@incoherent` basically says "I know what I'm doing, so don't emit errors about conflicts between these two types; just give me the Swift 2.1 behavior". I'm not sure why you think the current behavior is not confusing, but `@incoherent`'s behavior is very confusing.
More information about the swift-evolution