Skip to content

reflect.DeepEqual does not function correctly for Int values. #56991

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mediaexchange-io opened this issue Nov 30, 2022 · 5 comments
Closed

reflect.DeepEqual does not function correctly for Int values. #56991

mediaexchange-io opened this issue Nov 30, 2022 · 5 comments

Comments

@mediaexchange-io
Copy link

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

$ go version
go version go1.19.3 darwin/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/paul/Library/Caches/go-build"
GOENV="/Users/paul/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/paul/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/paul/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.19.3/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.19.3/libexec/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.19.3"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/paul/Projects/mediaexchange-io/assert/go.mod"
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 x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/d3/gklpfnbs4dlcg4q03kw2dv7w0000gq/T/go-build1420062890=/tmp/go-build -gno-record-gcc-switches -fno-common"
GOROOT/bin/go version: go version go1.19.3 darwin/amd64
GOROOT/bin/go tool compile -V: compile version go1.19.3
uname -v: Darwin Kernel Version 21.6.0: Thu Sep 29 20:12:57 PDT 2022; root:xnu-8020.240.7~1/RELEASE_X86_64
ProductName:	macOS
ProductVersion:	12.6.1
BuildVersion:	21G217
lldb --version: lldb-1400.0.38.13
Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)

What did you do?

https://go.dev/play/p/tVGd49zEvBc

What did you expect to see?

Output of both lines should be true

What did you see instead?

reflect.DeepEqual returned false.

Details

According to the documentation for DeepEqual:

Other values - numbers, bools, strings, and channels - are deeply equal if they are equal using Go's == operator`

Apparently when comparing an ints of different widths, promotion isn't used by DeepEqual. Funny enough, this used to work. I think when the function was changed to func DeepEqual(x, y any) bool from func DeepEqual(x, y interface{}) bool this broke.

@dsnet
Copy link
Member

dsnet commented Nov 30, 2022

This is working as intended since the types are different. It's no different than this logic:

fmt.Println(any(int64(-128)) == any(-128)) // reports false

@mediaexchange-io
Copy link
Author

mediaexchange-io commented Nov 30, 2022

Before any was introduced to the language, this worked. Whether intentional or not, the behavior of DeepEqual changed between versions of Go. The comment in the code didn't change. Go's == operator promotes int8 to int64 in this case, and the comparison succeeds.

So either the change in behavior was intentional and the docs were not updated, or the functionality was broken. Either way, this issue should be reviewed.

@fzipp
Copy link
Contributor

fzipp commented Nov 30, 2022

@mediaexchange-io
No, it worked the same in Go 1.17. You can check it yourself:

go install golang.org/dl/go1.17@latest
go1.17.3 download
go1.17.3 run issue.go

any(introduced in Go 1.18) is just an alias for interface{}. It doesn't change the behaviour.

@cuonglm
Copy link
Member

cuonglm commented Nov 30, 2022

@mediaexchange-io Quote from the doc:

Two values of identical type are deeply equal if one of the following cases applies. Values of distinct types are never deeply equal.

In reflect.DeepEqual(int64(-128), -128), int64(-128) has type int64, -128 is an untyped constant, and in the context that required typed value, it's converted to int. Those values are distinct types, so never deeply equal.

At least go1.4 also reports false.

@mediaexchange-io
Copy link
Author

@cuonglm This is really odd. I had some code from the 1.12 timeframe that I'm in the process of updating to 1.19. It depended on DeepEqual and passed all of its tests. After I bumped the Go version, tests began to fail. At this point I can't explain why it worked previously, but it did.

I'll close this issue since the current behavior is reproducible as far back as 1.4.

@golang golang locked and limited conversation to collaborators Nov 30, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants