I'm wondering if the following code should actually compile:
protocol P {}
protocol R {
func f(p: any P)
}
struct S: R {
func f(p: some P) {}
}
In other words, can a (some P) -> () method fulfill the protocol requirement (any P) -> ()?
A recent Swift 6.0.2 compiler doesn't accept it. What are cases where any P and some P are different as method parameters? I feel they should be equivalent. Aren't they in certain circumstances?
Even the generic version could be accepted as a conforming implementation of the method. T: P being equivalent to some P should be the same as any P in this case.
Theoretically, the code could be allowed. To create S's protocol witness for R.f(p:), the compiler would just need to generate the code to unwrap the existential and then call S.f(p:) on it.
However, this would cause problems in today's Swift, since unfortunately the overload resolution system prefers existential parameters over generic ones. This means that R's f(p:) would always get picked over S's, even if you're directly calling f(p:) on an instance of S.
I'd like to see this aspect of overload resolution be fixed someday, but it probably won't be soon since it would be a breaking change.