This was previously discussed here, but the discussion seems to have dropped off:
In the time since that was posted, while investigating how difficult it would be to support, I found that the existing constraints fully support this feature, and it's purely restricted syntactically.
I would like to propose we lift this restriction, which would allow using type inference in more places, e.g. specializing function references.
For example, ideally I would like to be able to write a function like this, which uses contextual information to determine what the decoding output.
final class MyDecoder: Decoder {
func decode<T>(from data: Data) throws -> T
}
In order to use it, I either have to pass it to a context which I know the type is derivable, or provide a type annotation. In both cases, I have to somewhat play constraint solver on behalf of the compiler, lining up the types such that the constraint system is satisfied:
let value: MyType = try decoder.decode(from: data)
// or pass it to a function:
func processValue(_ value: MyType) { ... }
processValue(try decoder.decode(from: data))
or as a coercion
let value = decoder.decode(from: data) as MyType
But what I really want is to be able to provide the type arguments the same way I provide the function arguments, using the same syntax the type parameters are declared with:
let value = decoder.decode<MyType>(from: data)
This is already supported for type instantiation when resolving constructor declarations:
let value = Array<MyType>()
And you can form partially applied functions referencing these instantiated constructors:
struct GenericValue<T> { var value: T }
let createGenericValue = GenericValue<Int>.init
The canonical workaround that has become accepted in Swift is to provide the generic parameter as a metatype argument:
func decode<T>(_ type: T.Type, from: Data) throws -> T
But that requires providing MyType.self, which is not something someone new to Swift would know to do. Many languages support this kind of explicit specialization for functions at the call site: C++, Java, Rust, C#, to name a few.
I think this restriction should be lifted, and I also think this should be preferred over the metatype parameter versions of generic functions like this. There's still value in taking meta types, like withTaskGroup's returning: argument label. That said, I think there's an argument to be made for labeled generic parameters as well.
I have an experimental PR up now to lift the restriction and update the tests. It generally does what you'd expect.
Thoughts? I would also appreciate more information if I'm missing something about the necessity of the restriction.