danielhall
(Daniel Hall)
1
If I declare a typealias for a concrete type in a protocol, e.g.
struct A { }
protocol P {
typealias Element = A
}
and then I write an extension based on that typealias on a conforming type, e.g.:
struct Conforming: P { }
extension Conforming.Element { // This should be identical to `extension A`
var success: Bool { true }
}
The compiler allows it. But trying to access the extension property will fail:
print(Conforming.Element().success) //Compiler error: "Value of type 'Conforming.Element' (aka 'A') has no member 'success'"
I declare the extension directly on the type (not through the typealias), e.g.
extension A {
var success: Bool { true }
}
Then the same print statement (accessing type A through the protocol typealias) will succeed
Declaring the typealias directly on the type allows the extension through the typealias to work:
struct Conforming {
typealias Element = A
}
extension Conforming.Element {
var success: Bool { true }
}
print(Conforming.Element().success) // "true"
It only seems to fail on the requirement of writing an extension that refers to a typealias declared by a protocol.
Is this a bug? Does anyone have any ideas for workarounds?
Ultimately what I want to accomplish is something like this (just a convenience really)
protocol SettingsProvider {
typealias SettingsConfiguration = Configuration<Self>
}
struct Configuration<T> { }
struct ConcreteType: SettingsProvider { }
// I want to be able to do this
extension ConcreteType.Settings {
var someProperty: String
}
// Instead of this equivalent that seems much less intuitive to me
extension Configuration<ConcreteType> {
var someProperty: String
}
2 Likes
xwu
(Xiaodi Wu)
2
Yup, seems like a bug. The workaround would be to declare the extension without using the alias, as you're doing.
4 Likes
xwu
(Xiaodi Wu)
4
Would you mind filing a bug over on the Swift GitHub issues tracker?
The bug was that it was not diagnosed. However, the type checker is rejecting the extension because it doesn't fit the implementation model. Extension binding has to happen very early, before other name lookups take place, so it cannot depend on conformance lookup tables having been constructed. For this reason, you cannot extend a protocol type alias accessed as a member of a concrete type.
I already fixed the diagnostic on main a while ago so I'm closing the bug: Sema: Improved check for failure to bind an extension by slavapestov · Pull Request #60364 · apple/swift · GitHub
5 Likes
danielhall
(Daniel Hall)
7
Thanks so much for your rapid attention and helpful explanation @Slava_Pestov!