Skip to content

go/types, types2: monomorphization check is too conservative for method declarations #80172

Description

@JasonMing

Go version

go version go1.27rc1 darwin/arm64

Output of go env in your module/workspace:

AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE='on'
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN='/Users/xxx/go/bin'
GOCACHE='/Users/xxx/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/xxx/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/hd/kktxntgs1fbf1k91l62nfb6m0000gn/T/go-build682996315=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/xxx/example/go.mod'
GOMODCACHE='/Users/xxx/go/pkg/mod'
GOOS='darwin'
GOPACKAGESDRIVER=''
GOPATH='/Users/xxx/go'
GOROOT='/Users/xxx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27rc1.darwin-arm64'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/xxx/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/xxx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27rc1.darwin-arm64/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.27rc1'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

I tried to compile this minimal program:

example_test.go

package p

type A[T any]struct{}

func (a A[T]) M() A[[]T] {
	panic("TODO")
}

func F[T any](a A[T]) A[[]T] {
	panic("TODO")
}

func TestFoo(t *testing.T) {
	A[string]{}.M() // Bad
	F(A[string]{})  // OK
}

Run:

go test ./...

The top-level function F compiles if the method M is removed.
The failure only appears when the same return type is used as the result of the generic method.

What did you see happen?

./example_test.go:7:8: instantiation cycle:
	./example_test.go:9:21: T instantiated as []T

What did you expect to see?

I expected the method to compile, or for the restriction to be documented as an intentional limitation of generic methods.

The method result type appears finite and statically knowable, and the equivalent top-level generic function compiles.
From the accepted generic methods proposal, concrete generic method calls are statically resolved, so this looks like the monomorphization cycle check may be treating the receiver type parameter as recursively instantiated when it appears inside the result type.

If this is an intended restriction, it would help to document why a generic method cannot return the receiver generic type instantiated with a type derived from the receiver type parameter, while an equivalent top-level generic function can.

Relevant background links:

Metadata

Metadata

Assignees

Labels

compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions