你正在使用的Go版本是什么( go version
)?
$ go version
go version go1.20.2 darwin/arm64
这个问题在最新版本的发布中是否会重现?
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/r/Library/Caches/go-build"
GOENV="/Users/r/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/r/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/r/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/Users/r/sdk/go1.20.2"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/r/sdk/go1.20.2/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.2"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/r/workspace/testcode/testinlinegeneric/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 -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/j_/rq9ph2cd3h50w468sgv34lwh0000gn/T/go-build2389814434=/tmp/go-build -gno-record-gcc-switches -fno-common"
GOROOT/bin/go version: go version go1.20.2 darwin/arm64
GOROOT/bin/go tool compile -V: compile version go1.20.2
uname -v: Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:37 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T6000
ProductName: macOS
ProductVersion: 13.2.1
BuildVersion: 22D68
lldb --version: lldb-1400.0.38.17
Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
你做了什么?
go.mod:
module test/inlinegeneric
go 1.20
a/a.go:
package a
type Foo1[T any] struct {
}
func (*Foo1[T]) Run() {
}
type Foo2 struct {
}
func (*Foo2) Run() {
}
b/b.go:
package b
import "test/inlinegeneric/a"
func Bar() {
var f1 a.Foo1[int]
f1.Run()
var f2 a.Foo2
f2.Run()
}
type Boo struct {
f1 a.Foo1[int]
f2 a.Foo2
}
main.go:
package main
import "test/inlinegeneric/b"
func main() {
var x b.Boo
_ = x
b.Bar()
}
go1.20.2 build --gcflags="-m=2" ./main.go
go1.19.7 build --gcflags="-m=2" ./main.go
你期望看到什么?
对于go1.20.2:
# command-line-arguments
./main.go:5:6: can inline main with cost 20 as: func() { b.Bar() }
./main.go:8:7: inlining call to b.Bar
./main.go:8:7: inlining call to a.(*Foo1[go.shape.int]).Run
./main.go:8:7: inlining call to a.(*Foo2).Run
对于go1.19.7
# command-line-arguments
./main.go:5:6: can inline main with cost 20 as: func() { b.Bar() }
./main.go:8:7: inlining call to b.Bar
./main.go:8:7: inlining call to a.(*Foo1[go.shape.int_0]).Run
./main.go:8:7: inlining call to a.(*Foo2).Run
你实际上看到了什么?
对于go1.20.2:
# command-line-arguments
./main.go:5:6: can inline main with cost 27 as: func() { x = <nil>; _ = x; b.Bar() }
./main.go:8:7: inlining call to b.Bar
./main.go:8:7: inlining call to a.(*Foo2).Run
./a/a.go:6:6: can inline a.(*Foo1[go.shape.int]).Run with cost 0 as: method(*a.Foo1[go.shape.int]) func(*[0]uintptr) { }
./a/a.go:6:6: can inline a.(*Foo1[int]).Run with cost 9 as: method(*a.Foo1[int]) func() { var .autotmp_0 *a.Foo1[int]; .autotmp_0 = <nil>; (*a.Foo1[go.shape.int]).Run(.autotmp_0, &a..dict.Foo1[int]) }
./a/a.go:6:6: inlining call to a.(*Foo1[go.shape.int]).Run
对于go1.19.7
# command-line-arguments
./main.go:5:6: can inline main with cost 27 as: func() { var x b.Boo; x = <nil>; _ = x; b.Bar() }
./main.go:8:7: inlining call to b.Bar
./main.go:8:7: inlining call to a.(*Foo2).Run
./a/a.go:6:17: can inline a.(*Foo1[go.shape.int_0]).Run with cost 0 as: func(uintptr, *a.Foo1[go.shape.int_0]) { }
4条答案
按热度按时间ehxuflar1#
See #57505 . Closing as a dup.
dvtswwa32#
See #57505 . Closing as a dup.
I don't think this issue is same as #57505 .
Neither go1.19 nor go1.20 nor go1.20 with non-unified does inline the method of the generic type.
But in #57505 , only go1.20 does not inline.
And I found that if we remove the field f1 in b.Boo struct or remove the variable x in main, then go1.20 will do inline the method, but go1.19 or non-unified will not inline.
b/b.go:
main.go:
go1.19.7 & go1.20 non-unified: None of the methods Run of Foo1[T] or Foo2[T] is inlined.
go1.20: Only Foo1[T].Run is not inlined, Foo2[T].Run is inlined. And the difference between Foo1[T] and Foo2[T] is that Boo has a field of type Foo1[T] and Boo is used in main package.
sulc1iza3#
你能明确指出哪些函数你希望内联,但没有吗?是
a.(*Foo1[go.shape.int]).Run
没有被内联到main
中吗?仅仅粘贴诊断信息而不解释是不清晰的。谢谢。我发现如果我们从 b.Boo 结构体中移除字段 f1 或者从 main 中移除变量 x,那么 go1.20 将内联方法。
所以,听起来
a.Foo1[int]
的两个示例,一个在b.Boo
中,另一个在b.Bar
中(内联到main
)导致编译器困惑?此外,它似乎不需要两级导入。即使我将
Foo1
和Foo2
的定义放入包b
中,似乎(*Foo1[go.shape.int]).Run
仍然没有被内联到main
中。cc @mdempsky@thanm @golang/compiler
ar7v8xwq4#
你能明确指出哪些函数你希望内联,但实际上没有内联吗?是
a.(*Foo1[go.shape.int]).Run
没有被内联到main
吗?仅仅粘贴诊断信息而不解释不清楚。谢谢。是的,a.(*Foo1[go.shape.int]).Run 预期会被内联到
main
,但实际上并没有。我发现如果我们从 b.Boo 结构体中移除字段 f1 或者从 main 中移除变量 x,那么 go1.20 将会内联该方法。
所以,听起来
a.Foo1[int]
的两个示例(一个在b.Boo
中,另一个在b.Bar
中,内联到main
)导致了编译器的困惑?是的。
此外,它似乎不需要两级导入。即使我将
Foo1
和Foo2
的定义放入 packageb
中,似乎(*Foo1[go.shape.int]).Run
仍然没有被内联到main
中。cc @mdempsky@thanm @golang/compiler
是的,不需要 package
a
。