You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
go/types: types.Error.go116end end position derived from placeholder Ident.Name is garbage #81876
Type-checking the code below results in a types.Error whose hidden go116end field (which gopls accesses via reflection) is invalid:
package p
typeIinterface{ M() }
varmmap[int]intfunc_() {
varaintvarbIa, b=m[0] // error: cannot use ok value of (comma, ok) expression ... as I value_, _=a, b
}
Standalone repro:
package main
import (
"fmt""go/ast""go/parser""go/token""go/types""reflect"
)
funcmain() {
for_, src:=range []string{
`package p; type I interface{ M() }; var m map[int]int; func _() { var a int; var b I; a, b = m[0]; _, _ = a, b }`,
`package p; type I interface{ M() }; func f() (int, int); func _() { var a I; var b int; a, b = f(); _, _ = a, b }`,
} {
fset:=token.NewFileSet()
f, _:=parser.ParseFile(fset, "a.go", src, 0)
conf:= types.Config{Error: func(errerror) {
e:=err.(types.Error)
v:=reflect.ValueOf(e)
start, end:=v.FieldByName("go116start").Int(), v.FieldByName("go116end").Int()
fmt.Printf("%s\n\tspan [%d,%d) len=%d; file size %d\n", e.Msg, start, end, end-start, len(src))
}}
conf.Check("p", fset, []*ast.File{f}, nil)
}
}
It prints:
cannot use ok value of (comma, ok) expression (value of type bool) as I value in multiple assignment: bool does not implement I (missing method M)
span [94,128) len=34; file size 112
cannot use 1st function result (value of type int) as I value in multiple assignment: int does not implement I (missing method M)
span [96,115) len=19; file size 113
The start position is accurate but the end is not, as it is derived from the length of the error description crammed by (*Checker).multiExpr into the Ident.Name field.So len("ok value of (comma, ok) expression") == 34 and len("1st function result") == 19. Both values fall past EOF and land in an unrelated file. A similar pattern appears in genericExprList. These bogus end positions are the root cause of the crash in gopls described in #81814.
A fix would be to use the real extent for the error span and carry the description separately.
Activity
gopherbot commentedon Oct 3, 2026
Change https://go.dev/cl/844245 mentions this issue:
go/types: preserve source spans for synthetic operandsdmitshur commentedon Oct 5, 2026
CC @griesemer, @mrkfrmn.