go: cmd/compile: invalidly inferred type for interface that doesn't use type parameter
In the following code:
type T[P any] interface {
m()
}
func g[P any](T[P]) {}
func _() {
var x T[int]
g(x) // here we infer P == int, but in fact any type of P would be ok
g[string](x) // here we set P == string
}
we infer the type int
for P
of g
. But in fact any type would make this code work. Type inference should not succeed in this case.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 26 (18 by maintainers)
Commits related to this issue
- go/types, types2: use exact unification for component types This change defines two unification modes used to control unification: - assign set when unifying types involved in an assignment - exact... — committed to golang/go by griesemer a year ago
- go/types, types2: use exact unification for component types This change defines two unification modes used to control unification: - assign set when unifying types involved in an assignment - exact... — committed to golangFame/go by griesemer a year ago
I think the framing provided by @griesemer and @atdiar is useful: if the solution is not unique, inference should fail. Otherwise, we run the risk of inferring a different type in the future (and that’s exactly why we need the special case currently).
I’ll note that there are other cases where there is one unique solution, and inference fails because of the current implementation:
@hajimehoshi in general to express units.
I’d think.
But your question is more interesting and I responded a bit too fast, since you are especially targeting the case of interface types.
I’m curious as well to see what people think.
@atdiar Your 2nd example will work with the fix.
Exactly, that’s why inference fails.
It’s a case similar to f(x) = c where c is constant.
Given c, we are still trying to find the one value of x that we passed to f.
That’s what was meant by unique, I don’t disagree at all.
g(T[int](x))
is the same asg(x)
ifx
is of typeT[int]
. Sog(T[string](nil))
currently works but would fail if we consider this issue a bug. Considerg[int](T[string](nil))
which works either way.In other words, currently we have an exception for defined generic interface types: if a defined generic interface type
T
which is instantiated with a concrete typeX
(assuming there’s one type parameter) is then matched against the same interface type “instantiated” with a type parameter, we infer the typeX
for the type parameter, even if the type parameter is never used by the methods:T[X]
unified againstT[P]
leads to the inference ofX
forP
.If we consider this issue a bug, then a) we don’t need an exception anymore, but b) in this example we wouldn’t be able to infer
X
anymore.I think this is a pretty esoteric case and doesn’t really justify the exception.
See also #8082 which applies when the interface types are components of other types.