Hi Kevin,
Thanks for your thoughts. In general, I think I’m going to put off thinking
more about the more general extension-shadowing warning until the related
proposal on swift-evolution is decided upon, as decisions made there will
undoubtedly impact what will trigger this warning and how to resolve it.
I’ll continue to work on the more specialized warning Doug brought up.
A few more comments below for when if/when we circle back to this.
> On Jan 3, 2016, at 7:33 PM, Kevin Ballard <[email protected]> wrote:
>
> On Sun, Jan 3, 2016, at 09:30 AM, Jesse Rusak wrote:
>> Some things from Kevin:
>>
>>> But the warning that Jesse was talking about, the one that was discussed in
>>> the older threads, I think is completely different. If I declare a method
>>> on my type that matches a protocol extension method, it is not safe to
>>> assume I was trying to override the (non-overridable) method. It's very
>>> likely that I'm simply providing a specialization of the method that will
>>> be called by anyone who's working with my type directly (with the
>>> acknowledgement that working with the type generically won't call my type's
>>> version).
>>
>>
>> Can I ask for examples of cases where you’d want to do this intentionally?
>> In those cases, would moving such members (or the protocol conformance) to
>> an extension be a hassle? The point about stored properties is one way this
>> is awkward; are there others?
>
> The suggested way to suppress the warning wasn't for this warning. It was for
> the warning about trying to conform to a protocol but having a member that
> doesn't actually match the protocol requirements (e.g. having a
> CollectionType with a `func generate()` that returns a type that doesn't
> actually conform to `GeneratorType`).
>
> The warning we're discussing here, of attempting to override a protocol
> extension method even though it's not a member of the protocol, can't work
> with this suppression mechanism unless the warning simply doesn't work at all
> for subclasses who inherit the protocol from their superclass. If you inherit
> the protocol declaration, then you can't possibly put the protocol
> conformance into its own extension because you're not declaring the
> conformance to begin with.
My intent was that you could move the conflicting member into an extension
rather than the conformance in the case when the main class declaration
conforms to a protocol or inherits it from its superclass. (Same proviso about
stored properties, of course.)
> Even if you ignore classes, the suppression mechanism doesn't really work for
> this warning anyway as it would suppress a lot of the cases that you actually
> want to warn about. I say that because it seems quite reasonable for people
> to declare things like `var last` in an extension on a type (which would
> trigger this suppression mechanism). This is doubly true for members declared
> with where clauses, because those are required to be in extensions (and can't
> declare protocol conformance). So e.g. if I say
>
> struct MyCollection<Base : CollectionType> : CollectionType {
> // ...
> }
>
> extension MyCollection where Base.Index : BidirectionalIndexType {
> var last: Generator.Element? {
> // ...
> }
> }
>
> then, assuming you think the warning is valid to begin with, you'd want to
> warn about that `var last`.
Sure, we might miss that. I will add it to the “we should try to get this” pile.
>>> My belief is that a warning in this case would end up being unwanted in a
>>> disproportionate number of cases. I believe it's better to clearly
>>> differentiate between protocol methods and extension methods and how they
>>> behave in our documentation and education for programmers than to add
>>> spurious warnings that will annoy everyone who does understand the
>>> distinction.
>>
>> How often are you doing this intentionally in your code? If it’s frequent,
>> we should see if there’s a way to suppress it for your common cases.
>
> I don't currently have any examples of this in my code. But I've also never
> had any cases where the warning would have triggered either. But the standard
> library provides examples of this!
>
> SequenceType has an extension that declares a `var lazy`. LazySequence also
> declares `var lazy`. It's obviously not overriding SequenceType's `lazy`
> property (especially because the type is slightly different), but it is very
> intentionally trying to shadow it, to make it so anyone who types
> `foo.lazy.lazy` gets back a `LazySequence<Foo>` instead of a
> `LazySequence<LazySequence<Foo>>`.
>
> Same thing also happens with `SequenceType.flatMap` and
> `LazySequence.flatMap`.
>
> CollectionType and LazyCollection is another example. At the very least the
> `lazy` property is an example. I'm not sure offhand if there's any other
> examples with those types but I wouldn't be surprised to find that there are.
>
> Set defines a method `contains(_ element:)` that's an exact match for the
> SequenceType extension method `contains(_ element:)`, but that's not actually
> an override. It also has `indexOf(_:)` which matches CollectionType's
> extension method `indexOf(_:)`.
>
> There may be others, I didn't do an exhaustive search of the standard
> library. But these should illustrate legitimate use-cases for shadowing
> protocol extension methods.
Thanks for this! I will definitely be looking through the rest of the standard
lib for other examples.
- Jesse_______________________________________________
swift-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-dev