Skip to content

cmd/compile: inconsistent error messages based on type constraints #53692

@sethvargo

Description

@sethvargo

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

$ go version
go version go1.18.3 darwin/arm64

Does this issue reproduce with the latest release?

Yes, including tip as of today

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

go env Output
$ go env

GO111MODULE="on"
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/sethvargo/Library/Caches/go-build"
GOENV="/Users/sethvargo/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/sethvargo/Development/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/sethvargo/Development/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.18.3/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.18.3/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.3"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
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 -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/cp/qb9vbbkx4w36f6dclng481br00gy5b/T/go-build4094322222=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I suspect the root cause of my actual issue is #41176, but it would be great if @ianlancetaylor can confirm for me 😄.

Playground link for the code: https://go.dev/play/p/RqzqQxNapkw. Note this code does not compile.

Code:

package main

// Cache is a generic cache implementation.
type Cache[K comparable, V any] interface {
	Get(K)
	Set(K, V)
}

// LRU is a cache.
type LRU[K comparable, V any] struct{}

func (l *LRU[K, V]) Get(key K)        {}
func (l *LRU[K, V]) Set(key K, val V) {}

// WithLocking1 returns a cache that wraps operations in a mutex.
func WithLocking1[K comparable, V any, C Cache[K, V]](cache C) {}

// WithLocking2 returns a cache that wraps operations in a mutex.
func WithLocking2[K comparable, V any](cache Cache[K, V]) {}

// WithLocking3 returns a cache that wraps operations in a mutex.
func WithLocking3[K comparable](cache Cache[K, any]) {}

func main() {
	var lru LRU[string, int]

	WithLocking1[string, int](&lru) // ok
	WithLocking1[string](&lru)      // nok: cannot infer V
	WithLocking1(&lru)              // nok: cannot infer K

	WithLocking2[string, int](&lru) // ok
	WithLocking2[string](&lru)      // nok: does not match Cache[string, V]
	WithLocking2(&lru)              // nok: cannot infer K and V

	WithLocking3[string](&lru) // nok: does not implement Cache[string, any] (wrong type for method Set)
	                           //   have Set(key string, val int)
	                           //   want Set(string, any)
	WithLocking3(&lru) // nok: cannot infer K
}

What did you expect to see?

As shown in the comments, the error messages are all subtly different depending on the type declarations on the function. I would expect the same error messages here.

What did you see instead?

Different error messages.

Aside

As an aside, it's unclear to me what the "correct" authorship is here. I really appreciate Go's "do one thing", but there seems to be multiple ways to define generics, all of which are subtly different with unknown consequences.

Metadata

Metadata

Assignees

Labels

FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.TypeInferenceIssue is related to generic type inferencecompiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions