This came up for us today -- in a situation like this:
class Super {}
class Sub : Super {}
protocol P {
var property: Super {get}
}
struct S : P {
var property: Sub
}
Currently Swift will error that Type 'S' does not conform to protocol 'P' because the property type is not an exact match. When the protocol only requires {get}, though, it ought to be safe to allow for covariance in the witness, shouldn't it?
In theory, yes (SR-522). In practice, that might result in a dangerous number of behavior changes, where things that previously weren't considered valid witnesses might now be considered a better match.
I really do not see what those behavior changes might be. @jrose do you have any exemples?
I feel like this feature would be awesome, and already see a ton of usages for it.
protocol P {
func foo(_ x: String)
}
extension P {
func foo(_ x: String) { print("default \(x)") }
}
struct S : P {
func foo(_ x: String?) { print("concrete \(x ?? "")") }
}
(S() as P).foo("abc") // currently prints "default abc"
I'm not saying these behavior changes are necessarily bad ones. But it's definitely a potentially silent change in the meaning of existing code, and that's something that would probably need a new language mode (-swift-version 6 or whatever).
To be clear: I was only proposing covariance for {get} properties, not for all witnesses (i.e. not for functions at all). Since you can't have multiple declarations of properties that differ only by type, I don't think that this could actually do anything unexpected for existing code.
protocol P {
var foo : String? {get}
}
extension P {
var foo : String? { "default" }
}
struct S : P {
var foo : String { "concrete" }
}
S().foo // "concrete"
(S() as P).foo // currently "default", would be "concrete" with this change
Seems really edge-case-y to me, but I'm not the one who has to deal with complaints, I guess.