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: "cannot infer T" in Go 1.21 (regression from Go 1.20) #63873

Closed
aykevl opened this issue Nov 1, 2023 · 5 comments
Closed

cmd/compile: "cannot infer T" in Go 1.21 (regression from Go 1.20) #63873

aykevl opened this issue Nov 1, 2023 · 5 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. TypeInference Issue is related to generic type inference
Milestone

Comments

@aykevl
Copy link

aykevl commented Nov 1, 2023

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

$ go version
go version go1.21.3 linux/arm64

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='arm64'
GOBIN=''
GOCACHE='/home/ayke/.cache/go-build'
GOENV='/home/ayke/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/ayke/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ayke'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go1.21.3'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go1.21.3/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.21.3'
GCCGO='gccgo'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/ayke/src/ayke/board/go.mod'
GOWORK='/home/ayke/src/ayke/go.work'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -pthread -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1813455582=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Run this program: https://go.dev/play/p/jx329NFz7ZU

What did you expect to see?

It compiles.

What did you see instead?

It fails to compile in Go 1.21, while it still compiled in Go 1.20.

Go 1.21 error message:

./prog.go:12:12: cannot infer T (prog.go:15:17)

I have code like this as an assert to verify that v (in the main function) is of a particular type.

@mauri870 mauri870 added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. compiler/runtime Issues related to the Go compiler and/or runtime. labels Nov 1, 2023
@mauri870
Copy link
Member

mauri870 commented Nov 1, 2023

/cc @golang/compiler

@seankhliao seankhliao added the TypeInference Issue is related to generic type inference label Nov 1, 2023
@cherrymui cherrymui changed the title cmd/go: "cannot infer T" in Go 1.21 (regression from Go 1.20) cmd/compile: "cannot infer T" in Go 1.21 (regression from Go 1.20) Nov 1, 2023
@cherrymui cherrymui added this to the Go1.22 milestone Nov 1, 2023
@bcmills
Copy link
Contributor

bcmills commented Nov 1, 2023

(attn @griesemer)

@griesemer griesemer self-assigned this Nov 1, 2023
@griesemer
Copy link
Contributor

This was a bug that was fixed for Go 1.21. The type parameter T of Foo is not used anywhere in Foo and thus one could infer an arbitrary type (or in this case either int or uint) and it would work.

More concretely, here's a slightly modified version of your example: checkMatch takes an extra argument of type T, and the call passes a uint argument y. The rest of the code is unchanged.

func main() {
	var v Foo[int]
	var y uint
	checkMatch(v, y)
}

func checkMatch[T Integer](v Foo[T], s T) {}

This code correctly infers uint for T in Go 1.21, but if fails in Go 1.20 because inference incorrectly infers int from the Foo[int] argument v which then conflicts with the uint inferred from the uint argument y.

For the original discussion see #60377.

Closing as working as intended.

@aykevl
Copy link
Author

aykevl commented Nov 1, 2023

Right, I see.

Apart from the assert, I used the type parameter to instantiate the right version of whatever was using v. This was quite useful. But now it seems I actually need to use the type somewhere in Foo[T].

My specific use case was a method on Foo (actually called Displayer) that accepts an image buffer in a particular format. Because the concrete type was written before generics, the parameter is basically just a raw byte buffer. So by calling a generic function with a Displayer[T] type where T was the pixel format, it can create the byte buffer in the requested format to pass to that method.

Here is a simplified version of what I'm doing: https://go.dev/play/p/PXuOVTqWMmZ
It compiles in Go 1.20, but doesn't compile in Go 1.21.

Anyway, I guess I'll have to add methods with the actual requested type (basically, giving the parameter to Update a type). It is a regression for my particular use case, but I can fix my code. I was probably not using generics as intended here.

@griesemer
Copy link
Contributor

griesemer commented Nov 1, 2023

As you say, you could add a dummy method (playground).
We understood only after 1.18 that inference must not infer a type if there is more than one possible choice because if can lead to inference failure when it clearly should succeed.

(I suppose one could try to make it work for both cases, but that would probably be complicated to explain.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. TypeInference Issue is related to generic type inference
Projects
None yet
Development

No branches or pull requests

6 participants