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: function.Origin() panics with "index out of range" #59427

Closed
aykevl opened this issue Apr 4, 2023 · 7 comments
Closed

x/tools/go/ssa: function.Origin() panics with "index out of range" #59427

aykevl opened this issue Apr 4, 2023 · 7 comments
Assignees
Labels
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.
Milestone

Comments

@aykevl
Copy link

aykevl commented Apr 4, 2023

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

$ go version
go version go1.20.2 darwin/arm64

Does this issue reproduce with the latest release?

Yes, 1.20.2 is the latest release.

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

go env Output
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN="/Users/ayke/bin"
GOCACHE="/Users/ayke/Library/Caches/go-build"
GOENV="/Users/ayke/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/ayke/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/ayke/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.20.2/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.20.2/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.2"
GCCGO="gccgo"
AR="ar"
CC="cc"
CXX="c++"
CGO_ENABLED="1"
GOMOD="/Users/ayke/src/ayke/sandbox/ssabug/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/17/btmpymwj0wv6n50cmslwyr900000gn/T/go-build3633563543=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

To reproduce:

What did you expect to see?

I expected .Origin() (last line of the program) to return something sensible.

What did you see instead?

It panics. Here is the complete output of the program, including all debug prints:

~/src/ayke/sandbox/ssabug$ go run .
Test: ssabug/testa.Test
# Name: ssabug/testa.Test
# Package: ssabug/testa
# Location: /Users/ayke/src/ayke/sandbox/ssabug/testa/testa.go:7:6
func Test():
0:                                                                entry P:0 S:0
	t0 = ssabug/value.Map[int]()                 ssabug/value.ValueItf[int]
	return

map call: ssabug/value.Map[int]()
map fn: ssabug/value.Map[int]
# Name: ssabug/value.Map[int]
# Synthetic: instance of Map
# Location: /Users/ayke/src/ayke/sandbox/ssabug/value/value.go:16:6
func Map[int]() ValueItf[int]:
0:                                                                entry P:0 S:0
	t0 = new Mapper[int] (complit)                             *Mapper[int]
	t1 = make ValueItf[int] <- *Mapper[int] (t0)              ValueItf[int]
	return t1

make inst: make ValueItf[int] <- *Mapper[int] (t0)
method: (*ssabug/value.Mapper[int]).Get[int]
# Name: (*ssabug/value.Mapper[int]).Get[int]
# Synthetic: instance of Get
# Location: /Users/ayke/src/ayke/sandbox/ssabug/value/value.go:11:21
func (m *Mapper[int]) Get[int](fn func()):
0:                                                                entry P:0 S:0
	t0 = &m.V [#0]                                           *ValueItf[int]
	t1 = *t0                                                  ValueItf[int]
	t2 = invoke t1.Get((*Mapper[int]).Get[int]$1)                        ()
	return

param: (*ssabug/value.Mapper[int]).Get[int]$1
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
golang.org/x/tools/go/ssa.(*Function).Origin(0x140002d6a80)
	/Users/ayke/go/pkg/mod/golang.org/x/tools@v0.7.0/go/ssa/ssa.go:1543 +0x70
main.readPackage(0x140002d4080)
	/Users/ayke/src/ayke/sandbox/ssabug/main.go:58 +0x400
main.main()
	/Users/ayke/src/ayke/sandbox/ssabug/main.go:31 +0x180
exit status 2

Note: I have also found a race condition when working with two SSA packages in a sing
le *ssa.Program that contains generics, but haven't been able to create a solid reproducer yet. I do feel like this bug could be related to that race condition.

Original issue found in tinygo-org/tinygo#3593.

@gopherbot gopherbot added the Tools This label describes issues relating to any tools in the x/tools repository. label Apr 4, 2023
@gopherbot gopherbot added this to the Unreleased milestone Apr 4, 2023
@mknyszek mknyszek added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Apr 4, 2023
@mknyszek
Copy link
Contributor

mknyszek commented Apr 4, 2023

CC @golang/tools-team

@timothy-king timothy-king self-assigned this Apr 6, 2023
@timothy-king
Copy link
Contributor

IIUC the key issue seems to be that in the test, the following happens:

  • ssa.Packages ssabug/testa and ssabug/value are created.
  • testa imports value.
  • testa is pkg.Build() value is not pkg.Build().
  • InstantiateGenerics is on.
  • value.Map[int]() is built. So (*ssabug/value.Mapper[int]).Get[int] is built too.
  • The test then asks for the Origin of (*ssabug/value.Mapper[int]).Get[int]$1.
  • (*ssabug/value.Mapper[T]).Get[T]$1 has not been built and its body & AnonFuncs list is empty.
  • There is the seen array out of bounds access.

This can be resolved by making sure the "value" package is built before asking for the Origin. Or by building the ssa.Program.

I think my question is what are you hoping for the "sensible" output to be? Are you hoping to get nil as the result? Are you hoping for the "value" package to get built if you happened to request this? A more user friendly panic message?

FWIW are you sure you do not want to build value as a stub package? (See buildssa for how to do this.) You would not have the body of (*ssabug/value.Mapper[int]).Get[int] either if this is how this was built.

Note: I have also found a race condition when working with two SSA packages in a single *ssa.Program that contains generics, but haven't been able to create a solid reproducer yet.

I'll be happy to take a look once you have more info.

@aykevl
Copy link
Author

aykevl commented May 2, 2023

Thank you for investigating!

I think my question is what are you hoping for the "sensible" output to be? Are you hoping to get nil as the result? Are you hoping for the "value" package to get built if you happened to request this? A more user friendly panic message?

I am not entirely sure. At the very least, a more useful panic message would go a long way. Also, documentation that says how this case should be handled would be helpful, something like "Origin() on a function instantiated from a different package needs to have that package already built" - not sure how to phrase this correctly.

FWIW are you sure you do not want to build value as a stub package? (See buildssa for how to do this.) You would not have the body of (*ssabug/value.Mapper[int]).Get[int] either if this is how this was built.

Hmm, perhaps I need to do this. I think the last time I tried this I ran into some issues, but I can try again.

What I really want is to get the AST node from which the generic function was built. Unfortunately, Syntax() returns nil on instantiated functions. Hence why I need to call Origin() to get the generic function so I can call Syntax(). If Origin() doesn't work across packages, then I don't think there is an API to do what I want. Do you have any suggestions?

Note: I have also found a race condition when working with two SSA packages in a single *ssa.Program that contains generics, but haven't been able to create a solid reproducer yet.

I'll be happy to take a look once you have more info.

I'm pretty sure this is a related bug, as I build the programs in parallel (which means that one pkg.Build() might not be finished before another package starts accessing its generic functions - this works fine outside generics). But if it's still present after I find a fix for the index out of range panic, then I can file a separate bug.

@gopherbot
Copy link

Change https://go.dev/cl/491735 mentions this issue: go/ssa: keep syntax for instantiations

@gopherbot
Copy link

Change https://go.dev/cl/491755 mentions this issue: go/ssa: Origin is only available after building

@aykevl
Copy link
Author

aykevl commented May 2, 2023

Building the dependencies first indeed appears to fix the problem. It does complicate the build a little bit though.

gopherbot pushed a commit to golang/tools that referenced this issue May 5, 2023
Keep the Syntax() for function instantiations when the origin package
has debug info enabled.

Updates golang/go#59427

Change-Id: I0a2a6ad2abbcec8226ef044510926dae33a2471a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/491735
Run-TryBot: Tim King <taking@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
@aykevl
Copy link
Author

aykevl commented Sep 26, 2023

Note: I have also found a race condition when working with two SSA packages in a single *ssa.Program that contains generics, but haven't been able to create a solid reproducer yet.

I'll be happy to take a look once you have more info.

I have finally managed to make a reproducer for this race condition, and made a bug report here: #63247

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.
Projects
None yet
Development

No branches or pull requests

4 participants