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/gopls: Hover: invalid nil entry in types.Defs map #69362

Closed
adonovan opened this issue Sep 9, 2024 · 14 comments
Closed

x/tools/gopls: Hover: invalid nil entry in types.Defs map #69362

adonovan opened this issue Sep 9, 2024 · 14 comments
Assignees
Labels
gopls/telemetry-wins gopls Issues related to the Go language server, gopls. 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

@adonovan
Copy link
Member

adonovan commented Sep 9, 2024

#!stacks
"runtime.sigpanic" && ("golang.hover:+170" || "golang.hover:+209" || "golang.hover:+216")

This stack zUGLQA was reported by telemetry:

if def, ok := pkg.TypesInfo().Defs[ident]; ok && ident.Pos() == def.Pos() {

Looks like Defs[ident]=nil is an actual map entry. This is confirmed by #69362 (comment).

crash/crash
runtime.gopanic:+69
runtime.panicmem:=262
runtime.sigpanic:+19
golang.org/x/tools/gopls/internal/golang.hover:+170
golang.org/x/tools/gopls/internal/golang.Hover:+4
golang.org/x/tools/gopls/internal/server.(*server).Hover:+30
golang.org/x/tools/gopls/internal/protocol.serverDispatch:+335
golang.org/x/tools/gopls/internal/lsprpc.(*streamServer).ServeStream.ServerHandler.func3:+5
golang.org/x/tools/gopls/internal/lsprpc.(*streamServer).ServeStream.handshaker.func4:+52
golang.org/x/tools/gopls/internal/protocol.Handlers.MustReplyHandler.func1:+2
golang.org/x/tools/gopls/internal/protocol.Handlers.AsyncHandler.func2.2:+3
runtime.goexit:+0

golang.org/x/tools/[email protected] go1.23.0 darwin/amd64 vscode (1)

Issue created by golang.org/x/tools/gopls/internal/telemetry/cmd/stacks.
Dups: ylB3Iw x2v5eg v95MAw

@adonovan adonovan added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository. gopls/telemetry-wins labels Sep 9, 2024
@gopherbot gopherbot added this to the Unreleased milestone Sep 9, 2024
@adonovan
Copy link
Member Author

adonovan commented Sep 9, 2024

I can't explain this one. The only three calls to recordDef(id, nil) in the type checker are for:

  1. package id
  2. switch id := expr.(type) {}
  3. the blank identifier in _ = expr.

It can't be (1) because the Hover logic handled the package clause specially at L186. It can't be (2) because this would cause referencedObject to return a non-nil third result (selectedType), causing an early return. And it can't be (3) because that would cause referencedObject not to return a non-nil Object, Ident pair, leading to an early return.

Clearly there is a mistake in my logic. But where?

@findleyr
Copy link
Member

Agreed. I think the best we'll be able to do here is downgrade the panic into two or more bug reports that refine the panic.

This is not the first "can't happen" bug related to go/types...

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/627015 mentions this issue: gopls/internal/golang: refine crash report golang/go#69362

@findleyr findleyr modified the milestones: gopls/v0.17.0, gopls/v0.18.0 Nov 11, 2024
gopherbot pushed a commit to golang/tools that referenced this issue Nov 11, 2024
This CL splits the various fallible checks that may have
been responsible for the crash report in golang/go#69362 onto
separate lines so that we can confirm whether a nil
map entry is indeed the cause. (I am almost certain that
it is, but I still can't explain it.)

Updates golang/go#69362

Change-Id: I0469e285bda65c21e80a348af04ea0e69f6a31c0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/627015
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Alan Donovan <[email protected]>
Reviewed-by: Robert Findley <[email protected]>
dennypenta pushed a commit to dennypenta/tools that referenced this issue Dec 3, 2024
This CL splits the various fallible checks that may have
been responsible for the crash report in golang/go#69362 onto
separate lines so that we can confirm whether a nil
map entry is indeed the cause. (I am almost certain that
it is, but I still can't explain it.)

Updates golang/go#69362

Change-Id: I0469e285bda65c21e80a348af04ea0e69f6a31c0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/627015
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Alan Donovan <[email protected]>
Reviewed-by: Robert Findley <[email protected]>
@findleyr
Copy link
Member

findleyr commented Feb 6, 2025

Well, the new stack is clearly a lie! Bumping this to 0.18.1, when we can hopefully have accurate stacks.

@findleyr findleyr modified the milestones: gopls/v0.18.0, gopls/v0.18.1 Feb 6, 2025
@adonovan
Copy link
Member Author

adonovan commented Feb 7, 2025

I have a theory: of the three cases listed above, the type-switch one is the most plausible. In order to reach the assertion, we must have gotten the triple (ident != nil, obj != nil, selectedType == nil) from referencedObject. Of the three return statements in referencedObject, this implicates only the one after the call to typeSwitchImplicits, and means that typeSwitchImplicits must have returned (empty slice, nil Type). Looking at the return statements within typeSwitchImplicits, this implicates only the final one (the other two are unreachable due to preconditions of this call). So, we have a type switch with an empty Body.List, and there is missing type information for the operand of the type switch: switch x := y.(type) {}.

The question then becomes: what syntax could y be to cause the type checker not to record a type for it? This would likely be a type checker bug. I looked for recent "no type recorded for expr" bugs but didn't find anything promising.

Still, I think this implicates the behavior of the type checker on a certain input with at least two compilation errors.

@adonovan
Copy link
Member Author

adonovan commented Feb 7, 2025

Ah, blaming the "may be nil" comment on the TypeOf call brought me to #69092 (comment), which records that we decided types may always be nil and that we should be defensive. So perhaps the right thing to do here is to return types.Invalid if the TypeOf call fails; then hover will take the early return and not reach the Defs lookup.

@findleyr
Copy link
Member

findleyr commented Feb 7, 2025

@adonovan FWIW I tried to follow your lead, and it may be a dead end: types.Checker.expr always records a type (possibly invalid), and inside the type checker we call expr on the asserted expression before we record any implicits https://cs.opensource.google/go/go/+/master:src/go/types/stmt.go;l=740;drc=c9afcbade7308cf66b67b9ce080f10b621b17c6a

So we can't have implicits with no RHS type.

@adonovan adonovan changed the title x/tools/gopls: crash in Hover (telemetry) x/tools/gopls: Hover: invalid nil entry in types.Defs map Feb 24, 2025
@adonovan
Copy link
Member Author

The most recent stack shows definitively that the types.Defs map contains a nil value.

@findleyr
Copy link
Member

findleyr commented Feb 24, 2025

I repro'ed!

switch x := y.(type) { // y is undefined!
case int:
}

Test+fix incoming.

@findleyr findleyr modified the milestones: gopls/v0.18.2, gopls/v0.18.1 Feb 24, 2025
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/652015 mentions this issue: gopls/internal/golang: fix crash when hovering over implicit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gopls/telemetry-wins gopls Issues related to the Go language server, gopls. 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