See https://go-review.googlesource.com/c/go/+/247478
For the real-world cases see https://github.com/VKCOM/noverify/blob/77ed62ed18e976f619031a5c828ea1f4b49c15ba/src/ir/irutil/clone.go#L219
That code was initially auto-generated, but it has a minor problem: it did F().(T)
even in cases where F()
already returns T
. This is not a big problem, but since this optimization is so simple to implement in the compiler, maybe we can do it?
What version of Go are you using ( go version
)?
$ go version
go version devel +5c7748dc9d Mon Aug 10 23:44:58 2020 +0000 linux/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="/home/isharipov/.cache/go-build"
GOENV="/home/isharipov/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPRIVATE=""
GOPROXY=" [https://proxy.golang.org,direct](https://proxy.golang.org,direct) "
GOROOT="/home/isharipov/CODE/go/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/isharipov/CODE/go/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build237409555=/tmp/go-build -gno-record-gcc-switches"
What did you do?
Compile this program:
package foo
import "io"
func example1(x io.Reader) io.Reader {
return x
}
func example2(x io.Reader) io.Reader {
return x.(io.Reader)
}
What did you expect to see?
Both example1
and example2
compiled to the same (efficient) code without type assertions.
What did you see instead?
example1
produces the type assertion CALL runtime.assertI2I(SB)
(and a lot of code around it, as expected).
3条答案
按热度按时间ilmyapht1#
请注意,当
x
是nil
时,example2
应该发生恐慌,而example1
则不应该。nwsw7zdq2#
嗯。我错过了一个微妙的细节。如果这个重写违反了正确性(看起来是这样),我们可以关闭这个问题(和CL)。
lb3vh1jj3#
它确实可以,尽管你可以以比调用
assertI2I
更便宜的方式进行空值检查。虽然可能没有便宜多少——assertI2I
首先执行空值检查和身份接口转换检查。