Skip to content
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

Open
arvidfm opened this issue Jun 15, 2022 · 5 comments
Assignees
Labels
NeedsDecision Thinking TypeInference
Milestone

Comments

@arvidfm
Copy link

@arvidfm arvidfm commented Jun 15, 2022

What version of Go are you using (go version)?

$ go version
go version go1.18.2 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/user/.cache/go-build"
GOENV="/home/user/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/user/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/user/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3440234987=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I tried compiling the below program.

https://go.dev/play/p/QcWycysXf-F?v=gotip

package main

type X[T any] struct{}

type Y struct{}

func F[T any](x X[T], y T) {}

func main() {
	x := X[any]{}
	F(x, any(Y{})) // works
	F[any](x, Y{}) // works
	F(x, Y{})      // error: type Y of Y{} does not match inferred type any for T
}

What did you expect to see?

I expected F(x, Y{}) to be equivalent to F[any](x, Y{}), and thus compile without issue.

What did you see instead?

F(x, Y{}) failed to compile with the following error:

type Y of Y{} does not match inferred type any for T
@seankhliao seankhliao added the NeedsInvestigation label Jun 15, 2022
@seankhliao
Copy link
Contributor

@seankhliao seankhliao commented Jun 15, 2022

cc @randall77 @griesemer

@griesemer griesemer self-assigned this Jun 15, 2022
@griesemer griesemer added NeedsDecision and removed NeedsInvestigation labels Jun 15, 2022
@griesemer griesemer added this to the Go1.20 milestone Jun 15, 2022
@griesemer
Copy link
Contributor

@griesemer griesemer commented Jun 15, 2022

Thanks for reporting this. Currently, type inference tries to matches each argument/parameter pair. So in this case, it infers the type any for T but any is not equal to the type Y, hence the failure.

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 F1 and F2 since parameters and arguments are swapped symmetrically. With the current implementation we get two errors:

x.go:12:8: type Y of y does not match inferred type any for T
x.go:13:8: type X[any] of x does not match inferred type X[Y] 

If inference would stop as soon as all type parameters are known we get one error (the call to F1 works):

x.go:13:8: cannot use x (variable of type X[any]) as X[Y] value in argument to F2

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.

@ianlancetaylor ianlancetaylor added the TypeInference label Jun 15, 2022
@beoran
Copy link

@beoran beoran commented Jun 23, 2022

@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.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jun 23, 2022

@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.

@beoran
Copy link

@beoran beoran commented Jun 23, 2022

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsDecision Thinking TypeInference
Projects
None yet
Development

No branches or pull requests

5 participants