swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.59k stars 10.37k forks source link

[SR-11791] Generic parameter conflict with nested iterator #54201

Open natecook1000 opened 5 years ago

natecook1000 commented 5 years ago
Previous ID SR-11791
Radar None
Original Reporter @natecook1000
Type Bug

Attachment: Download

Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug | |Assignee | @slavapestov | |Priority | Medium | md5: 55e235db0319c7b83e185abee50f3418

Issue Description:

I have a Tree type that is generic over Element, and defines a nested iterator that has its own element type implicitly declared as Tree<Element>. (See attached file.) This compiles without error in shipping Swift, but in swift-DEVELOPMENT-SNAPSHOT-2019-11-14-a I get this error:

IteratorElement.swift:20:12: error: type 'Tree<Element>.Iterator' does not conform to protocol 'IteratorProtocol'
    struct Iterator: IteratorProtocol {
           ^
IteratorElement.swift:48:23: note: candidate has non-matching type '<Element> () -> Tree<Element>?' [with Element = Element]
        mutating func next() -> Tree? {
                      ^
Swift.IteratorProtocol:3:19: note: protocol requires function 'next()' with type '() -> Element?'
    mutating func next() -> Self.Element?
                  ^

I can fix the problem by changing the name of Tree's generic parameter to TreeElement.

slavapestov commented 5 years ago

I reverted the change in question, however I can bring it back without breaking your code, because note that 'Element' is not a generic parameter of Iterator itself, but of its outer type. It should not be a candidate for inference.

natecook1000 commented 5 years ago

So in your pitch (https://forums.swift.org/t/infer-associated-types-as-generic-parameters-more-eagerly/30833), only the generic parameters on the specific type conforming to a protocol P should be candidates for P's associated types? That makes sense.

slavapestov commented 5 years ago

Yes, that is correct. I believe it was an oversight that we always look at the "innermost" generic parameters even if the type is not generic.

slavapestov commented 5 years ago

Actually your code also relies on Sequence.Element := Tree\<Element> in the outermost type too, because the witness comes from the iterator's element type. So this would be another source break from my proposal unfortunately. Maybe the proposal isn't worth it?