mirror of https://github.com/golang/go.git
internal/lsp/source/completion: use typeutil.Map for short-circuiting
While working on golang/go#52715, I discovered an infinite recursion in gopls' completion logic: eachField assumes a finiteness of type pointers. It is almost certainly a go/types bug that type-checked types expand infinitely, but nevertheless we should use the more accurate typeutil.Map for short-circuiting our search. Change-Id: Ib1c7125e624f42882869acd4e0476e317d4da056 Reviewed-on: https://go-review.googlesource.com/c/tools/+/404335 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> Run-TryBot: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
d299b94661
commit
d7e01c038e
|
|
@ -9,6 +9,7 @@ import (
|
|||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/types/typeutil"
|
||||
"golang.org/x/tools/internal/lsp/diff"
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
|
|
@ -33,12 +34,12 @@ func eachField(T types.Type, fn func(*types.Var)) {
|
|||
// types.NewSelectionSet should do that for us.
|
||||
|
||||
// for termination on recursive types
|
||||
var seen map[*types.Struct]bool
|
||||
var seen typeutil.Map
|
||||
|
||||
var visit func(T types.Type)
|
||||
visit = func(T types.Type) {
|
||||
if T, ok := source.Deref(T).Underlying().(*types.Struct); ok {
|
||||
if seen[T] {
|
||||
if seen.At(T) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -46,12 +47,7 @@ func eachField(T types.Type, fn func(*types.Var)) {
|
|||
f := T.Field(i)
|
||||
fn(f)
|
||||
if f.Anonymous() {
|
||||
if seen == nil {
|
||||
// Lazily create "seen" since it is only needed for
|
||||
// embedded structs.
|
||||
seen = make(map[*types.Struct]bool)
|
||||
}
|
||||
seen[T] = true
|
||||
seen.Set(T, true)
|
||||
visit(f.Type())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue