-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
The Go 1.21 release introduced significantly improved type inference. Specifically:
A (possibly partially instantiated generic) function may now be called with arguments that are themselves (possibly partially instantiated) generic functions. The compiler will attempt to infer the missing type arguments of the callee (as before) and, for each argument that is a generic function that is not fully instantiated, its missing type arguments (new). [ ... ] More generally, a generic function may now be used without explicit instantiation when it is assigned to a variable or returned as a result value if the type arguments can be inferred from the assignment.
As stated, this type inference works in assignments, but it doesn't work for all assignments. For instance, given (playground):
type S struct{ f func(int) }
func g[T any](T) {}
func _(s S) {
s.f = g // ok
s = S{f: g} // error: cannot use generic function g without instantiation
s = S{f: g[int]} // ok
}The assignment of the generic function g to the function-typed field f of struct S works as described but the same (implicit) assignment to field f in the struct literal does not - explicit instantiation of g is required.
The same is true for assignments to array, slice, or map elements vs the same (implicit) assignment in the respective composite literals, and sends to channels (playground):
type F func(int)
type A [10]F
type S []F
type M map[string]F
type C chan F
func g[T any](T) {}
func _() {
var a A
a[0] = g // ok
a = A{g} // error: cannot use generic function g without instantiation
a = A{g[int]} // ok
var s S
s[0] = g // ok
s = S{g} // error: cannot use generic function g without instantiation
s = S{g[int]} // ok
var m M
m["foo"] = g // ok
m = M{"foo": g} // error: cannot use generic function g without instantiation
m = M{"foo": g[int]} // ok
var c C
c <- g // error: cannot use generic function g without instantiation
c <- g[int] // ok
}In all these cases we have an assignment where the type on the LHS is completely known and thus the function type parameter can be inferred unambiguously, and should be inferred for consistency.
While making this change likely requires some clarifications in the spec, I believe this is arguably a bug rather than a language change because the assignments (a[0] = g) work, but the implicit assignments in composite literals don't (a = A{g}). The exception is channel sends, but even in that case the element to be sent must be assignable to the channel element type and thus establishes a clear "target" type.
Correction:
The spec is explicit about where this inference is supposed to work (see Instantiations). I believe it makes sense to generalize to all assignment contexts but that requires a spec change and proposal.
Metadata
Metadata
Labels
Type
Projects
Status
Status