Description
This proposal suggests a generalization of type inference where type parameters of generic function values are inferred from assignments of those values to variables. Similar ideas have been suggested in the past, e.g. see #53138 and related issues mentioned in that issue.
Background
At the moment, and even with the proposed reformulation of type inference (#58650), type inference determines the type arguments of a generic function based on (partially) provided type arguments and function arguments passed to that generic function.
We propose that missing type arguments of generic functions be inferred when such generic function values are assigned to variables of function type. That is, rather than inferring the type arguments of the function being called (and values being passed to), we infer the type arguments of the function being passed from the function being called (hence reverse type inference for lack of a better term).
For instance, the generic function g
func g[P, Q any](x P) Q { ... }
may be assigned to a variable of function type
var f func(int) bool = g
and type inference will infer that P
must be int
and Q
must be bool
. The function g
may also be partially instantiated, so this assignment (after f
is declared) would be allowed as well
f = g[int]
More importantly, passing a generic function as a function value to another (possibly generic) function may infer the type arguments of the function value (and possibly of the generic function being called). Given
func less[P Ordered](x, y P) bool { return x < y }
func sort[Q any](list []Q, less func(x, y Q) bool) { ... }
we can call
sort(list, less)
and the type argument Q
of sort
will be inferred from the list
argument, and the type argument P
of less
will be inferred from passing less
to sort
.
Proposal
A generic function may not be fully instantiated when its (function) value is assigned to a variable of matching function type. In that case, type inference will infer any unknown type arguments, if possible.
For the purpose of this proposal, initialization expressions (to fully typed variables) in variable declarations, assignments to redeclared (and thus fully typed) variables in short variable declarations, returning results to function result parameters, and passing values to (user-defined) functions in function calls are considered assignments where this form of type inference will be applicable.
This is the entire proposal.
(Together with @ianlancetaylor.)
Implementation
We have a partial implementation (currently disabled in the dev branch) that implements significant aspects of this proposal (assignments and return statements, except passing arguments to generic functions) so that we can explore the ramifications. If this proposal is accepted, we hope to make the feature available for Go 1.21.