Skip to content

cmd/compile: counter-intuitive comparison of zero-sized pointers wrapped in interfaces #65878

Closed
@Merovius

Description

@Merovius

Go version

go version go1.22.0 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/mero/.cache/go-build'
GOENV='/home/mero/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/mero/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/mero'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/mero/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/home/mero/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.0'
GCCGO='/usr/bin/gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/mero/tmp/x/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-build624578175=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Playground:

package main

import "fmt"

func main() {
	a, b := new(struct{}), new(struct{})
	x, y := any(a), any(b)
	fmt.Println(a == b, x == y, x.(*struct{}) == y.(*struct{}))
}

What did you see happen?

false true false

What did you expect to see?

Either false false false or true true true.

The spec defines comparison for interfaces as:

Interface types that are not type parameters are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.

Now, from this definition, the observed behavior should clearly be impossible. The dynamic values are not equal - either before or after wrapping them into any. However, the interfaces compare as equal.

I suspect there is an optimization going on, where the comparison function stored in the rtype short-circuits for pointers to zero-sized values, based on the permission for all zero-sized values to have the same address. But that is only correct, if the compiler does the same short-circuiting for ==, in my opinion.

Originally mentioned on golang-nuts.

Metadata

Metadata

Assignees

Labels

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

Type

No type

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions