-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/compile: "type does not match inferred type" even though it compiles when the inferred type is explicitly provided as type argument #53389
Comments
Thanks for reporting this. Currently, type inference tries to matches each argument/parameter pair. So in this case, it infers the type If inference would stop as soon as all type arguments are known, this specific case would work. But we also want type inference to be independent of the ordering of the parameters/arguments. Consider this case: package p
type X[T any] struct{}
type Y struct{}
func F1[T any](X[T], T) {}
func F2[T any](T, X[T]) {}
func _() {
var x X[any]
var y Y
F1(x, y)
F2(y, x)
} where we'd expect no difference in behavior between the calls to
If inference would stop as soon as all type parameters are known we get one error (the call to
The current (implemented) behavior ensures that when ordering of parameters/arguments changes the outcome, one needs to provide explicit type arguments. This makes the code robust in the presence of such re-orderings. These calls: F1[any](x, y)
F2[any](y, x) work independent of parameter/argument ordering. Thus, this is working correctly as designed, but perhaps not as expected. Leaving open for now so that we don't lose sight of this as we refine type inference over time. |
@griesemer it seems to me that this could be solved by assigning a priority to each parameter/type parameter pair, where the highest priority is for type arguments of the lowest complexity (i.e just T, U, V etc) and then the higher order type arguments later (T[U], etc ). Then the order of the parameters does not matter either. |
@beoran I think it's extremely important that type inference be very easy to understand and completely predictable for anybody reading the code. I'm not sure your suggestion fits that model. |
@ianlancetaylor Well, yes, the current rule had the benefit of being much more easy to explain and understand. But it has the downside that in some cases it is not so easy to use. I'm not sure how the balance should be in this case. |
This issue is currently labeled as early-in-cycle for Go 1.21. |
Simpler reproducer (playground link): package main
func f[P any](P, P) {}
func _(x any, y int) {
f[any](x, y) // ok
f(x, y) // ERROR: type int of y does not match inferred type any for P
} Type inference uses unification to make types "equivalent" (essentially identical, but with slightly less stringent rules). Specifically, we make use of the fact that type identity (and thus type equivalence and unification) are symmetric: if x and y can be unified, then can y and x, and in both cases we get the same result. In order to make this example work, type inference would need to take into account assignment rules, which are nor symmetric: if x can be assigned to y, it's not a given that y can be assigned to x. This would likely make unification much more complicated. It would require that we take assignability into account. Perhaps it is possible, while retaining the property that it doesn't matter in which order type parameters are declared or function arguments are provided, but it's bound to be very complicated to implement and even more complicated to explain. Type inference is already pretty complicated; if anything we want to reduce complexity, not add more. In this specific case, and all cases where assignability matters, one can easily provide explicit type arguments and make the code compile. We're not going to make type inference work in cases like these. Closing as not planned. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I tried compiling the below program.
https://go.dev/play/p/QcWycysXf-F?v=gotip
What did you expect to see?
I expected
F(x, Y{})
to be equivalent toF[any](x, Y{})
, and thus compile without issue.What did you see instead?
F(x, Y{})
failed to compile with the following error:The text was updated successfully, but these errors were encountered: