+1
I hit this again the other day. We have really strange witness matching that often feels inconsistent.
For example, if you have a protocol requirement which accepts a concrete type, a generic method can witness it:
protocol MyProtocol {
func doSomething(_: String)
}
struct MyStruct: MyProtocol {
// Works, because String conforms to StringProtocol
func doSomething<S: StringProtocol>(_: S) { fatalError() }
}
So you might expect, if there is a protocol requirement which returns an existential, that a method which returns a concrete conforming type would also be able to witness it:
protocol MyProtocol {
func doSomething() -> any StringProtocol
}
struct MyStruct: MyProtocol {
// Computer says no.
func doSomething() -> String { fatalError() }
}
If the requirement has a default implementation, the type still conforms, but resolves to an unexpected implementation
The idea of only warning about these mismatches in extensions does not seem like an adequate solution, to me. Some types are designed to perform one task and be written in a single, compact declaration - so it is unusual that anybody would split the implementation up across extensions, and hence they would not receive any diagnostics. Types declared inside functions don't support extensions at all:
func someFunction() {
struct MyStruct {}
extension MyStruct {}
^^^^^^^^^
error: declaration is only valid at file scope
}