Here's the shortest example I could come up with while trying to reduce my real world scenario (which doesn't include Array or Collection):
protocol P {
associatedtype A: Collection where A.Element == Self
}
extension Collection where Self: P {
typealias A = Array<Self>
}
The above compiles successfully, but swapping Collection
and P
in the extension will result in compile time errors.
Details
collection_first.swift:
protocol P {
associatedtype A: Collection where A.Element == Self
}
extension Collection where Self: P {
typealias A = Array<Self>
}
p_first.swift:
protocol P {
associatedtype A: Collection where A.Element == Self
}
extension P where Self: Collection {
typealias A = Array<Self>
}
I can reproduce the behavior using both the default toolchain of Xcode 9.4 and the most recent snapshot:
› swiftc --version
Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2)
Target: x86_64-apple-darwin17.5.0
›
› /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-06-05-a.xctoolchain/usr/bin/swiftc --version
Apple Swift version 4.2-dev (LLVM 031e148970, Clang b58a7ad218, Swift 0747546bd7)
Target: x86_64-apple-darwin17.5.0
collection_first.swift compiles successfully:
› swiftc collection_first.swift
›
› /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-06-05-a.xctoolchain/usr/bin/swiftc collection_first.swift
›
p_first.swift fails to compile with the following errors (which are slightly different for the two versions of the compiler):
› swiftc p_first.swift
p_first.swift:2:40: error: type alias 'A' references itself
associatedtype A: Collection where A.Element == Self
^
p_first.swift:5:15: note: type declared here
typealias A = Array<Self>
^
p_first.swift:2:40: error: 'A' is ambiguous for type lookup in this context
associatedtype A: Collection where A.Element == Self
^
p_first.swift:2:20: note: found this candidate
associatedtype A: Collection where A.Element == Self
^
p_first.swift:5:15: note: found this candidate
typealias A = Array<Self>
^
p_first.swift:2:50: error: same-type requirement makes generic parameter 'Self' non-generic
associatedtype A: Collection where A.Element == Self
^
›
›
› /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-06-05-a.xctoolchain/usr/bin/swiftc p_first.swift
p_first.swift:2:40: error: type alias 'A' references itself
associatedtype A: Collection where A.Element == Self
^
p_first.swift:5:15: note: type declared here
typealias A = Array<Self>
^
p_first.swift:2:40: error: 'A' is ambiguous for type lookup in this context
associatedtype A: Collection where A.Element == Self
^
p_first.swift:2:20: note: found this candidate
associatedtype A: Collection where A.Element == Self
^
p_first.swift:5:15: note: found this candidate
typealias A = Array<Self>
^
›
Note that the same-type requirement is not necessary to reproduce the behavior, Self
can be replaced with eg Int
and the two variants of the program will still demonstrate this behavior.
This example is perhaps too reduced and contrived to show why I think there might be valid reasons rather than a compiler bug behind this. But I might well be wrong.
Maybe I can post a better example later, unless someone can bring clarity to this before that?