Closed
Description
Follow up to #38685 that seems to have solved a simple case but does not eliminate an unused interface method across packages
What version of Go are you using (go version
)?
[rojer@nbd /tmp]$ GOROOT=/home/rojer/go/go-git /home/rojer/go/go-git/bin/go version go version devel +b7e0adfee2 Fri Nov 6 07:55:52 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
[rojer@nbd /tmp]$ GOROOT=/home/rojer/go/go-git /home/rojer/go/go-git/bin/go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/rojer/.cache/go-build" GOENV="/home/rojer/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GOMODCACHE="/home/rojer/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/rojer/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/home/rojer/go/go-git" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/home/rojer/go/go-git/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/dev/null" 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-build351127229=/tmp/go-build -gno-record-gcc-switches"
What did you do?
source:
[rojer@nbd /tmp]$ find foobar/
foobar/
foobar/go.mod
foobar/foo
foobar/foo/foo.go
foobar/bar
foobar/bar/bar.go
[rojer@nbd /tmp]$ cat foobar/foo/foo.go
package main
import (
"foobar/bar"
)
func main() {
// Test unused method elimination.
var b bar.Interface
b = bar.Bar{}
b.UsedInterfaceMethod()
}
[rojer@nbd /tmp]$ cat foobar/bar/bar.go
package bar
import "fmt"
type Interface interface {
UsedInterfaceMethod()
UnusedInterfaceMethod()
}
type Bar struct{}
func (Bar) UsedInterfaceMethod() {
fmt.Println("one")
}
// This method is unused but cannot be eliminated yet.
// https://github.com/golang/go/issues/38685
func (Bar) UnusedInterfaceMethod() {
fmt.Println("two")
}
// This method is unused and should be eliminated.
func (Bar) UnusedNonInterfaceMethod() {
fmt.Println("three")
}
What did you expect to see?
foobar/bar.(*Bar).UnusedInterfaceMethod
should not make it into the final binary.
in fact, neither should foobar/bar.(*Bar).UsedInterfaceMethod
because pointer variant is not used.
in other words, all that should be left from bar.Bar
should be bar.Bar.UsedInterfaceMethod
.
interesting, that foobar/bar.Bar.UnusedInterfaceMethod
does get eliminated but not the bar.*Bar
variant.
why is it even generated in the first place?
What did you see instead?
[rojer@nbd /tmp/foobar/foo]$ GOROOT=/home/rojer/go/go-git /home/rojer/go/go-git/bin/go build
[rojer@nbd /tmp/foobar/foo]$ GOROOT=/home/rojer/go/go-git /home/rojer/go/go-git/bin/go tool nm -size foo | grep foobar/bar
497080 187 T foobar/bar.(*Bar).UnusedInterfaceMethod
497140 187 T foobar/bar.(*Bar).UsedInterfaceMethod
535e20 32 D foobar/bar..inittask
496fe0 138 T foobar/bar.Bar.UsedInterfaceMethod
4da288 40 R go.itab.foobar/bar.Bar,foobar/bar.Interface