golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.17k stars 17.56k forks source link

cmd/compile: type arguments for generic aliases are not checked against type parameter constraints #69576

Closed mneverov closed 4 days ago

mneverov commented 1 week ago

Go version

go version devel go1.24-c208b91395 Fri Sep 20 13:54:44 2024 +0000 X:aliastypeparams linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/mneverov/.cache/go-build'
GOENV='/home/mneverov/.config/go/env'
GOEXE=''
GOEXPERIMENT='aliastypeparams'
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/mneverov/go/pkg/mod'
GONOPROXY='gitlab.in.strato.de,github.com/ionos-cloud'
GONOSUMDB='gitlab.in.strato.de,github.com/ionos-cloud'
GOOS='linux'
GOPATH='/home/mneverov/go'
GOPRIVATE='gitlab.in.strato.de,github.com/ionos-cloud'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/mneverov/go/src/github.com/golang/go'
GOSUMDB='sum.golang.org'
GOTMPDIR='/home/mneverov/tmp'
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/mneverov/go/src/github.com/golang/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.24-c208b91395 Fri Sep 20 13:54:44 2024 +0000 X:aliastypeparams'
GODEBUG=''
GOTELEMETRY='on'
GOTELEMETRYDIR='/home/mneverov/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/mneverov/go/src/github.com/mneverov/usealias/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=/home/mneverov/tmp/go-build764456494=/tmp/go-build -gno-record-gcc-switches'

What did you do?

see in playground

// GOEXPERIMENT=aliastypeparams

package main

import "fmt"

type T[P int] struct{ f P }
type A[P int] = T[P]

func main() {
    var ta A[string]
    fmt.Printf("%#v\n", ta)
}

What did you see happen?

The output is main.T[string]{f:""}

What did you expect to see?

error string does not satisfy int (string missing in int)

gabyhelp commented 1 week ago

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

rittneje commented 1 week ago

As the error indicates, this is because you declared type A[P int], which means the generic type can only be int, hence string is not allowed.

Changing your variable to be var ta A[int], or changing your type declarations to be type T[P any] and type A[P any] resolves it.

seankhliao commented 1 week ago

as mentioned above, type aliases don't allow you to relax type constraints.

atdiar commented 1 week ago

Think it should be reopened. OP seems to wonder why it compiles. Seems like a bug.

(made the same mistake initially :)

mneverov commented 1 week ago

as mentioned above, type aliases don't allow you to relax type constraints.

I'm not relaxing the constraint with the alias. Declaring an alias with the same constraint as the initial type constraint eliminates it. The code compiles, but should error out FMPV.

ianlancetaylor commented 6 days ago

CC @griesemer @findleyr

This does look like a bug. The type alias permits type arguments that are not permitted by the constraint.

griesemer commented 5 days ago

It appears that we're not checking the constraints for alias type parameters at all. Simpler reproducer:

package p

type A[P int] = struct{}

var _ A[string] // no error reported here

Temp. work-around: write correct code...

cuonglm commented 5 days ago

It appears that we're not checking the constraints for alias type parameters at all. Simpler reproducer:

package p

type A[P int] = struct{}

var _ A[string] // no error reported here

Temp. work-around: write correct code...

It seems to me that when checking var type, we stop immediately as long as we see typeparam.

griesemer commented 5 days ago

@cuonglm This is unrelated to var types. It also happens if we declare another type that depends on A. The problem is that Checker.instantiatedType doesn't verify the instantiation if the instantiated type is an alias.

gopherbot commented 5 days ago

Change https://go.dev/cl/615275 mentions this issue: go/types, types2: check that alias type arguments satisfy constraints