Skip to content

cmd/compile: recursive generic interface instantiation error #65362

@carmichaeljr

Description

@carmichaeljr

Go version

go version go1.21.6 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/jcarmichael/.cache/go-build'
GOENV='/home/jcarmichael/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/jcarmichael/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/jcarmichael/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.6'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/mnt/c/Users/Lenovo/Documents/Programming/util/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1952531264=/tmp/go-build -gno-record-gcc-switches'

What did you do?

I wrote the code shown below and in the following playground link: https://go.dev/play/p/d8XxoEklO6D

package main

import "fmt"

type Comparisons[OI any, OIR any, K any, V any] interface {
	Difference(other OIR) OI
}

// An interface that only allows read operations on a vector.
type ReadVector[V any] interface {
	Comparisons[Vector[V], ReadVector[V], int, V]
}

// An interface that only allows write operations on a vector.
type WriteVector[V any] interface {
	otherMethods()
}

// An interface that represents a vector with no restrictions on reading or
// writing.
type Vector[V any] interface {
	ReadVector[V]
	WriteVector[V]
}

type VectorImpl[T any] struct{}

func (v *VectorImpl[T]) otherMethods() {}
func (v *VectorImpl[T]) Difference(other ReadVector[T]) Vector[T] {
	rv := VectorImpl[T]{}
	return &rv
}

func main() {
	v := VectorImpl[int]{}
	v2 := VectorImpl[int]{}
	var v2Interface Vector[int] = &v2
	fmt.Println(v.Difference(v2Interface))
}

What did you see happen?

The compiler produced the following error:

./prog.go:38:27: cannot use v2Interface (type ReadVector[int]) as type ReadVector[go.shape.int] in argument to (*VectorImpl[go.shape.int]).Difference:
	ReadVector[int] does not implement ReadVector[go.shape.int] (wrong type for Difference method)
		have Difference(ReadVector[int]) Vector[int]
		want Difference(ReadVector[go.shape.int]) go.shape.interface { main.otherMethods() }

Go build failed.

What did you expect to see?

I expected the program to compile and print the empty Vector[int] structure value.

Of note is if you change the second generic parameter on line 11 to Vector[int] as well as the corresponding type on the Difference method on line then the compiler successfully finishes, and the program works as intended.

I am not sure if this is relevant, but the compiler error does not list the difference method on the Vector return type of the Difference method in the error it produces. It prints this:

want Difference(ReadVector[go.shape.int]) go.shape.interface { main.otherMethods() }

when I think it should print something like this (formatting added for readability):

want Difference(ReadVector[go.shape.int]) go.shape.interface { 
    main.otherMethods() 
    main.Difference(
        ReadVector[go.shape.int]
    ) go.shape.interface{ main.otherMethods(); ReadVector[go.shape.int]} 
}

I am guessing on the syntax of the output shown above, I am just saying what would make sense to see based on what I am already seeing, I am sure the correct output is different.

I am not sure what the rules are regarding recursive interface type definitions as shown in the example, and the issue is only compounded by the added generics.

Metadata

Metadata

Labels

FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.genericsIssue is related to generics

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions