Since SE-0347 the following will compile as expected:
func compute<C: Collection>(_ values: C = [0, 1, 2]) { ... }
So, the compiler can successfully infer the type of a generic from a default value expression for the function parameter.
Now I encountered an issue in a more complex case which involves associated type inference where the compiler fails to infer the type and emits an error:
Given a protocol which is later used as a type constraint for that function parameter:
protocol Subject<Value> {
associatedtype Value
func send(_ value: Value)
}
and another protocol P with an associated type and a static function where the above protocol is used as the parameter:
protocol P {
associatedtype V
static func foo<S: Subject<V>>(subject: S)
}
Now I want to have a default implementation of the above static function which also sports a default parameter:
struct DefaultSubject<Value>: Subject {
func send(_ value: Value) {}
}
extension P {
static func foo<S: Subject<V>>(subject: S = DefaultSubject<V>()) {}
}
Now, I want to define an Enum type for my use case:
enum E: P {
typealias V = Int
}
So far so good. The compiler is happy.
But when I try to use it:
func test() async throws {
E.foo(subject: DefaultSubject()) // fine!
E.foo() // Error: Generic parameter 'S' could not be inferred
}
The compiler cannot infer the type in the second line!
My understanding is, when the compiler applies the default parameter it would try something like this:
let defaultParam = DefaultSubject<E.V>()
E.foo(subject: defaultParam)
}
which does compile.
It's also my understanding (I could be wrong, though) that for the compiler everything needed to figure out the types should be there.
So, what's going on?
Do I miss something?
How can I fix it, or what would be a possible workaround?
Copy&Paste Test
import Testing
protocol Subject<Value> {
associatedtype Value
func send(_ value: Value)
}
protocol P {
associatedtype V
static func foo<S: Subject<V>>(subject: S)
}
struct DefaultSubject<Value>: Subject {
func send(_ value: Value) {}
}
extension P {
static func foo<S: Subject<V>>(subject: S = DefaultSubject<V>()) {}
}
enum E: P {
typealias V = Int
}
@Test func test() async throws {
E.foo(subject: DefaultSubject()) // fine!
E.foo() // Generic parameter 'S' could not be inferred
let defaultParam = DefaultSubject<E.V>()
E.foo(subject: defaultParam)
}