Jumhyn
(Frederick Kellison-Linn)
1
Consider the following snippet:
protocol P<PT> {
associatedtype PT
}
struct AnyP<T>: P {
typealias PT = T
}
extension P {
func eraseToAnyP() -> AnyP<PT> {
AnyP()
}
}
protocol Q {
associatedtype QT: P<Int>
func f() -> QT
}
func g(_ q: any Q) {
q.f().eraseToAnyP() // error
}
in Xcode 14 beta 3, the q.f().eraseToAnyP() line results in a warning/error. The warning is that the result of q.f() is erased to any P, causing the subsequent error that eraseToAnyP() cannot be called on a value of type any P. However, at first glance it seems to me like this should be supported by erasing the result of q.f() to any P<Int> rather than any P.
Is this just a vestigial result of the SE-0309 erasure that wasn't updated to take SE-0353 into account, or is there a more fundamental limitation here that's escaping me?
Jumhyn
(Frederick Kellison-Linn)
2
cc @codafi @hborla happy to file this on GitHub but wanted a gut check to make sure there wasn't something I misunderstood here
hborla
(Holly Borla)
3
This looks like a bug to me too. SE-0353 specifies that covariant erasure can still be performed when the associated type is in invariant position and has been made concrete. I believe that covers the case you've written above. This code does work:
protocol P<PT> {
associatedtype PT
}
extension P where PT == Int {
func f() -> Self { self }
}
struct AnyP<T>: P {
typealias PT = T
}
extension P {
func eraseToAnyP() -> AnyP<PT> {
AnyP()
}
}
func g(p: any P<Int>) {
p.f().eraseToAnyP() // okay
}
which is slightly different, but the result of calling f() has the same generic constraints as far as I can tell!
1 Like