#!stacks
"runtime.gopanic" &&
"types.(*Checker).handleBailout:+7" &&
/* unfortunately there is no way to express bailout-within-bailout
so we must subtract all other patterns that use bailout */
!("go/types.setDefType:+7") // #71029
Issue created by stacks.
Well this is a weird one. Checker.Files. defers a function to recover from certain expected panics; that function re-panics for all other cases. However, the re-panic causes the deferred function to execute a second time (!). Presumably this means the defer bookkeeping (e.g. *_panic.deferBitsPtr
) has become corrupted.
func (check *Checker) handleBailout(err *error) {
switch p := recover().(type) {
case nil, bailout:
// normal return or early exit
*err = check.firstErr
default:
// re-panic
panic(p) <-- causes deferred call to check.handleBailout to execute again!
}
}
// Files checks the provided files as part of the checker's package.
func (check *Checker) Files(files []*ast.File) (err error) {
...
defer check.handleBailout(&err) <-- this closure is called repeatedly
check.checkFiles(files)
return
}
This stack k7voyQ
was reported by telemetry:
crash/crash
runtime.gopanic:+69
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
golang.org/x/tools/gopls@v0.18.1 go1.23.7 darwin/arm64 other (2)
Dups: 5qvnIw UFUvMw
Comment From: adonovan
cc: @golang/runtime
Comment From: gabyhelp
Related Issues
- go/types: panic("t.fromRHS = %s, typ = %s") in setDefType #71029 (closed)
- go/types: failed genericType assertion in Checker.instantiatedType #71198 (closed)
- x/tools/gopls: nil *types.Package panic in testKind #73096 (closed)
- x/tools/gopls: nil deref panic in go.test code action #72907 (closed)
- go/types: recursive type aliases might cause a panic #71284 (closed)
- go/types, types2: gopls crash in computeInterfaceTypeSet with "duplicate method" #51316 (closed)
- go/types: panic in new logic in recordCommaOkTypes #59371 (closed)
- go.tools/go.types: goto _ crashes type checker #7537 (closed)
- go/types, types2: index out of range panic in Checker.arguments #61931 (closed)
- go/types, types2: gopls crash on method with type parameters #50427 (closed)
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: adonovan
This stack PrtfKQ
was reported by telemetry:
crash/crash
runtime.gopanic:+69
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
go/types.setDefType:+7
go/types.(*Checker).typInternal:+175
go/types.(*Checker).definedType:+1
go/types.(*Checker).typeDecl:+55
go/types.(*Checker).objDecl:+141
go/types.(*Checker).packageObjects:+59
go/types.(*Checker).checkFiles:+29
go/types.(*Checker).Files:+13
golang.org/x/tools/gopls/internal/cache.(*typeCheckBatch).checkPackage:+73
golang.org/x/tools/gopls/internal/cache.(*typeCheckBatch).getPackage.func1:+49
golang.org/x/tools/gopls/internal/cache.(*futureCache[...]).get:+32
golang.org/x/tools/gopls/internal/cache.(*typeCheckBatch).getPackage:+1
golang.org/x/tools/gopls@v0.18.1 go1.23.7 darwin/arm64 other (1)
Comment From: mknyszek
In triage, @randall77 notes that it looks like the defer isn't properly taken off of the defer list, so it gets run twice. But what's weird is the first time defer is called is as an open-coded defer, and we only create the defer record the second time.
Comment From: randall77
I looked into this for a while, nothing obvious. All the compiler-generated metadata looks good. There are various defer wrappers that complicate things, but nothing obviously wrong.
My only guess is that a stack copy happens at exactly the wrong time, causing defer selection to fail. But that would, I think, only cause defers to be missed, not duplicated. But who knows. We're probably going to need a reproducer to make more progress.
Comment From: adonovan
We're probably going to need a reproducer to make more progress.
I suspect this just another the of many varied symptoms of a single bug causing memory corruption; see label. Unfortunately we haven't been able to (knowingly) reproduce any of them even once.
Comment From: adonovan
This stack 5qvnIw
was reported by telemetry:
crash/crash
runtime.gopanic:+69
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
go/types.assert:+8
go/types.(*Checker).validType0:+99
go/types.(*Checker).validType0:+27
go/types.(*Checker).validType0:+123
go/types.(*Checker).validType0:+27
go/types.(*Checker).validType0:+123
go/types.(*Checker).validType:=17
go/types.(*Checker).typeDecl.func1:+2
go/types.(*Checker).processDelayed:+16
go/types.(*Checker).stmt.deferwrap1:+0
runtime.deferreturn:+10
go/types.(*Checker).stmt:+476
go/types.(*Checker).stmtList:+9
golang.org/x/tools/gopls@v0.18.1 go1.23.8 darwin/arm64 vscode (1)
Comment From: adonovan
This stack UFUvMw
was reported by telemetry:
crash/crash
runtime.gopanic:+69
go/types.(*Checker).handleBailout:+7
go/types.(*Checker).Files.deferwrap1:+0
runtime.gopanic:+50
runtime.panicmem:=262
runtime.sigpanic:+19
go/types.samePkg:=234
go/types.(*Named).lookupMethod:+2
go/types.lookupFieldOrMethodImpl:+51
go/types.(*Checker).missingMethod:+41
go/types.(*Checker).hasAllMethods:+4
go/types.(*Checker).implements:+52
go/types.(*operand).assignableTo:+52
go/types.(*Checker).assignment:+87
go/types.(*Checker).compositeLit:+84
go/types.(*Checker).exprInternal:+32
go/types.(*Checker).rawExpr:+10
go/types.(*Checker).expr:+1
golang.org/x/tools/gopls@v0.18.1 go1.24.1 linux/amd64 vscode (1)
Comment From: adonovan
That last stack has a different cause, though clearly yet more memory corruption.