Skip to content
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

x/tools/go/ssa: panic: T #54274

Closed
iangudger opened this issue Aug 4, 2022 · 6 comments
Closed

x/tools/go/ssa: panic: T #54274

iangudger opened this issue Aug 4, 2022 · 6 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Tools This label describes issues relating to any tools in the x/tools repository. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@iangudger
Copy link
Contributor

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

$ go version
go version go1.19 linux/amd64

Does this issue reproduce with the latest release?

Yes

What did you do?

I'm using v0.34 of bazelbuild/rules_go's nogo functionality. This includes v0.1.11 of golang.org/x/tools. When I use either golang.org/x/tools/go/analysis/passes/nilness or golang.org/x/tools/go/analysis/passes/unusedwrite, I get a panic. I looked through all of the commits since v0.1.11 and none of them look like they would fix the issue. It would be difficult for me to test a newer version though.

Sample nilness panic

compilepkg: panic: T

goroutine 36 [running]:
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0002d09c0, {0x726a98?, 0xc000263c20?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:237 +0x5b9
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0002d09c0, {0x726a70?, 0xc000295c68?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:233 +0x710
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0002d09c0, {0x7269d0?, 0xc000277a50?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:182 +0x1d3
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0002d09c0, {0x726980?, 0xc000292a10?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:215 +0x565
golang.org/x/tools/go/ssa.(*Program).needMethodsOf(0xc0002d09c0, {0x726980?, 0xc000292a10?})
        external/org_golang_x_tools/go/ssa/methods.go:145 +0x70
golang.org/x/tools/go/ssa.(*Package).build(0xc0002df320)
        external/org_golang_x_tools/go/ssa/builder.go:2284 +0x111
sync.(*Once).doSlow(0xc0002d09c0?, 0xc0000f2e10?)
        GOROOT/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
        GOROOT/src/sync/once.go:65
golang.org/x/tools/go/ssa.(*Package).Build(...)
        external/org_golang_x_tools/go/ssa/builder.go:2272
golang.org/x/tools/go/analysis/passes/buildssa.run(0xc0002d08f0)
        external/org_golang_x_tools/go/analysis/passes/buildssa/buildssa.go:72 +0x2ee
main.(*action).execOnce(0xc0000bd440)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:301 +0x842
sync.(*Once).doSlow(0x0?, 0x0?)
        GOROOT/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
        GOROOT/src/sync/once.go:65
main.(*action).exec(0x0?)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:245 +0x3d
main.execAll.func1(0x0?)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:239 +0x54
created by main.execAll
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:237 +0x47
panic: interface conversion: interface {} is nil, not *buildssa.SSA

goroutine 35 [running]:
golang.org/x/tools/go/analysis/passes/nilness.run(0xc0004020d0)
        external/org_golang_x_tools/go/analysis/passes/nilness/nilness.go:64 +0xad
main.(*action).execOnce(0xc0000bd3b0)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:301 +0x842
sync.(*Once).doSlow(0x0?, 0x0?)
        GOROOT/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
        GOROOT/src/sync/once.go:65
main.(*action).exec(0x0?)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:245 +0x3d
main.execAll.func1(0x0?)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:239 +0x54
created by main.execAll
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:237 +0x47

Sample unusedwrite panic

compilepkg: panic: E

goroutine 79 [running]:
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0000c5110, {0x724488?, 0xc00023c8a0?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:237 +0x5b9
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0000c5110, {0x724410?, 0xc000236e20?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:196 +0x33a
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0000c5110, {0x724460?, 0xc00023ee28?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:233 +0x710
golang.org/x/tools/go/ssa.(*Program).needMethods(0xc0000c5110, {0x7243e8?, 0xc00027c080?}, 0x0)
        external/org_golang_x_tools/go/ssa/methods.go:209 +0x2e5
golang.org/x/tools/go/ssa.(*Program).needMethodsOf(0xc0000c5110, {0x7243e8?, 0xc00027c080?})
        external/org_golang_x_tools/go/ssa/methods.go:145 +0x70
golang.org/x/tools/go/ssa.(*Package).build(0xc0000e2c60)
        external/org_golang_x_tools/go/ssa/builder.go:2284 +0x111
sync.(*Once).doSlow(0xc0000c5110?, 0xc000239400?)
        GOROOT/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
        GOROOT/src/sync/once.go:65
golang.org/x/tools/go/ssa.(*Package).Build(...)
        external/org_golang_x_tools/go/ssa/builder.go:2272
golang.org/x/tools/go/analysis/passes/buildssa.run(0xc0000c5040)
        external/org_golang_x_tools/go/analysis/passes/buildssa/buildssa.go:72 +0x2ee
main.(*action).execOnce(0xc000161440)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:301 +0x842
sync.(*Once).doSlow(0x0?, 0x0?)
        GOROOT/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
        GOROOT/src/sync/once.go:65
main.(*action).exec(0x0?)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:245 +0x3d
main.execAll.func1(0x0?)
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:239 +0x54
created by main.execAll
        external/io_bazel_rules_go/go/tools/builders/nogo_main.go:237 +0x47
@gopherbot gopherbot added the Tools This label describes issues relating to any tools in the x/tools repository. label Aug 4, 2022
@gopherbot gopherbot added this to the Unreleased milestone Aug 4, 2022
@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 5, 2022
@dmitshur
Copy link
Contributor

dmitshur commented Aug 5, 2022

CC @timothy-king, @findleyr.

@timothy-king
Copy link
Contributor

What is the output of go list -m golang.org/x/tools for the tool you are using to build the nilness check? I know you mentioned v0.1.11 but sometimes folks refer to things like v0.1.11-0.20220316014157-77aa08bb151a as v0.1.11.

@timothy-king
Copy link
Contributor

timothy-king commented Aug 5, 2022

As you are on bazel the previous request for go list -m golang.org/x/tools might not make sense. Can you confirm more precisely what version the nilness is being built against?

I suspect you are compiling against a too old version. This is very similar to #54086

@iangudger
Copy link
Contributor Author

It is the version in https://github.com/golang/tools/archive/refs/tags/v0.1.11.zip.

https://github.com/bazelbuild/rules_go/blob/28e7e33ca1dd7adfd8371c7f5d9a6fd18f386fa1/go/private/repositories.bzl#L66-L73

@timothy-king
Copy link
Contributor

I am not able to reproduce this. Without being able to reproduce this my suspicion is still that your nogo binary has not been built using an up to date golang.org/x/tools (such as v0.1.11) FWIW. Are you sure it is up to date? (Also how are you sure? This might help me.)

Here is what I have tried so far. I bootstrapped bazel, created a blaze workspace with nogo analysis (using v0.34 of rules_go), created a mildly custom analyzer to inspect the ssa, created an example with features that should tickle this, and ran nogo on the example.

$BAZEL build //:hello gives the expected output: no crashes, there are generic methods called, generic types that flow into interfaces (so needsMethods should be called), and the ssa looks post v.01.11. The example is single directory containing the following: code under analysis (hello.go), the blaze + nogo setup (WORKSPACE, BUILD.bazel), and some extra analysis to dump buildssa (printbuildinfo.go). Included at the bottom.

I think I need more specific reproduction instructions at this point. Code under analysis? Blaze+nogo setup?

--- hello.go

package main

import "fmt"

type S[T any] struct{}

func (s S[T]) Foo() {}

func main() {
	fmt.Println("calling an fmt function")

	var s S[int]
	var i interface{ Foo() } = s
	i.Foo()

	var n *int
	if n == nil {
		println("expect a nilness complaint")
	}
}

--- WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "io_bazel_rules_go",
    sha256 = "16e9fca53ed6bd4ff4ad76facc9b7b651a89db1689a2877d6fd7b82aa824e366",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip",
        "https://github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip",
    ],
)

load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")

go_rules_dependencies()

go_register_toolchains(version = "1.18.3", nogo = "@//:my_nogo")

--- BUILD.bazel

load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

load("@io_bazel_rules_go//go:def.bzl", "nogo")

nogo(
    name = "my_nogo",
    deps = [
        ":printbuildinfo",
        "@org_golang_x_tools//go/analysis/passes/nilness:go_default_library",
    ],
    visibility = ["//visibility:public"], # must have public visibility
)

go_library(
    name = "printbuildinfo",
    srcs = ["printbuildinfo.go"],
    importpath = "printbuildinfo",
    deps = [
      "@org_golang_x_tools//go/analysis:go_default_library",
      "@org_golang_x_tools//go/analysis/passes/buildssa:go_default_library",
      "@org_golang_x_tools//go/ssa:go_default_library",
    ],
    visibility = ["//visibility:public"],
)

go_binary(
    name = "hello",
    srcs = ["hello.go"],
)

--- printbuildinfo.go

package printdebuginfo

import (
	"bytes"
	"go/token"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/passes/buildssa"
	"golang.org/x/tools/go/ssa"
)

var Analyzer = &analysis.Analyzer{
	Name:     "printdebuginfo",
	Doc:      "...",
	Run:      run,
	Requires: []*analysis.Analyzer{buildssa.Analyzer},
}

func run(pass *analysis.Pass) (interface{}, error) {
	ssainput := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)

	for fn := range AllFunctions(ssainput.Pkg.Prog) {
		var buf bytes.Buffer
		ssa.WriteFunction(&buf, fn)
		pass.Reportf(token.NoPos, "Function %s: %s", fn.String(), buf.String())
	}
	return nil, nil
}

func AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {
	visit := visitor{
		prog: prog,
		seen: make(map[*ssa.Function]bool),
	}
	visit.program()
	return visit.seen
}

type visitor struct {
	prog *ssa.Program
	seen map[*ssa.Function]bool
}

func (visit *visitor) program() {
	for _, pkg := range visit.prog.AllPackages() {
		for _, mem := range pkg.Members {
			if fn, ok := mem.(*ssa.Function); ok {
				visit.function(fn)
			}
		}
	}
	for _, T := range visit.prog.RuntimeTypes() {
		mset := visit.prog.MethodSets.MethodSet(T)
		for i, n := 0, mset.Len(); i < n; i++ {
			visit.function(visit.prog.MethodValue(mset.At(i)))
		}
	}
}

func (visit *visitor) function(fn *ssa.Function) {
	if !visit.seen[fn] {
		visit.seen[fn] = true
		var buf [10]*ssa.Value // avoid alloc in common case
		for _, b := range fn.Blocks {
			for _, instr := range b.Instrs {
				for _, op := range instr.Operands(buf[:0]) {
					if fn, ok := (*op).(*ssa.Function); ok {
						visit.function(fn)
					}
				}
			}
		}
	}
}

FWIW

$ $BAZEL --version
bazel 6.0.0-pre.20220720.3- (@non-git)

@timothy-king timothy-king added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Aug 5, 2022
@iangudger
Copy link
Contributor Author

@timothy-king you were right. My other Bazel config was downgrading golang.org/x/tools below the required version.

@golang golang locked and limited conversation to collaborators Aug 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Tools This label describes issues relating to any tools in the x/tools repository. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants