From 31afefa3eedc2699b0fb0abc16a6444a0234084e Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 20 May 2026 13:55:20 +0200 Subject: [PATCH 1/3] Fix panic on bare PkgName identifier references A bare *ast.Ident whose info.Uses entry is a *types.PkgName (e.g. 'var _ = sort' after 'import "sort"') is malformed Go, but the parser and type checker still record the use. Well-formed code routes such references through the *ast.SelectorExpr handler, but bare idents slipped through to GetSymbolOfObject and tripped its 'should never lookup PkgName ...' assertion. Skip bare *types.PkgName references in the file visitor so malformed source no longer crashes the indexer. --- internal/testdata/snapshots/input/pr261/README.md | 8 ++++++++ internal/testdata/snapshots/input/pr261/bare_pkg.go | 5 +++++ internal/testdata/snapshots/input/pr261/go.mod | 3 +++ internal/testdata/snapshots/output/pr261/bare_pkg.go | 12 ++++++++++++ internal/visitors/visitor_file.go | 4 ++++ 5 files changed, 32 insertions(+) create mode 100644 internal/testdata/snapshots/input/pr261/README.md create mode 100644 internal/testdata/snapshots/input/pr261/bare_pkg.go create mode 100644 internal/testdata/snapshots/input/pr261/go.mod create mode 100755 internal/testdata/snapshots/output/pr261/bare_pkg.go diff --git a/internal/testdata/snapshots/input/pr261/README.md b/internal/testdata/snapshots/input/pr261/README.md new file mode 100644 index 0000000..2c8f8a5 --- /dev/null +++ b/internal/testdata/snapshots/input/pr261/README.md @@ -0,0 +1,8 @@ +# Bare `PkgName` identifier + +`var _ = sort` is malformed Go but the parser accepts it and the type checker +still records `info.Uses[sort] = *types.PkgName`. Well-formed code routes such +uses through the `*ast.SelectorExpr` handler in `visitor_file.go`; a bare ident +slips past it into the generic reference path and previously hit the +`panic("should never lookup PkgName ...")` assertion in `lookup.go`. The visitor +now skips bare `*types.PkgName` references instead of crashing. diff --git a/internal/testdata/snapshots/input/pr261/bare_pkg.go b/internal/testdata/snapshots/input/pr261/bare_pkg.go new file mode 100644 index 0000000..ca1895c --- /dev/null +++ b/internal/testdata/snapshots/input/pr261/bare_pkg.go @@ -0,0 +1,5 @@ +package pr261 + +import "sort" + +var _ = sort diff --git a/internal/testdata/snapshots/input/pr261/go.mod b/internal/testdata/snapshots/input/pr261/go.mod new file mode 100644 index 0000000..2bba4a2 --- /dev/null +++ b/internal/testdata/snapshots/input/pr261/go.mod @@ -0,0 +1,3 @@ +module sg/pr261 + +go 1.23 diff --git a/internal/testdata/snapshots/output/pr261/bare_pkg.go b/internal/testdata/snapshots/output/pr261/bare_pkg.go new file mode 100755 index 0000000..e5147a9 --- /dev/null +++ b/internal/testdata/snapshots/output/pr261/bare_pkg.go @@ -0,0 +1,12 @@ + package pr261 +// ^^^^^ definition 0.1.test `sg/pr261`/ +// kind Package +// display_name pr261 +// signature_documentation +// > package pr261 + + import "sort" +// ^^^^ reference github.com/golang/go/src go1.22 sort/ + + var _ = sort + diff --git a/internal/visitors/visitor_file.go b/internal/visitors/visitor_file.go index 08c440a..36d9e87 100644 --- a/internal/visitors/visitor_file.go +++ b/internal/visitors/visitor_file.go @@ -225,6 +225,10 @@ func (v *fileVisitor) Visit(n ast.Node) ast.Visitor { // Emit Reference ref := info.Uses[node] if ref != nil { + if _, ok := ref.(*types.PkgName); ok { + return v + } + var ( symbol string deprecated bool From 803cf59ffcd3dc2af2aa198b08faacaba672883a Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 20 May 2026 13:58:31 +0200 Subject: [PATCH 2/3] Clarify pr261 README: 'malformed' -> 'syntactically valid but ill-typed' --- .../testdata/snapshots/input/pr261/README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/internal/testdata/snapshots/input/pr261/README.md b/internal/testdata/snapshots/input/pr261/README.md index 2c8f8a5..1570ea3 100644 --- a/internal/testdata/snapshots/input/pr261/README.md +++ b/internal/testdata/snapshots/input/pr261/README.md @@ -1,8 +1,12 @@ # Bare `PkgName` identifier -`var _ = sort` is malformed Go but the parser accepts it and the type checker -still records `info.Uses[sort] = *types.PkgName`. Well-formed code routes such -uses through the `*ast.SelectorExpr` handler in `visitor_file.go`; a bare ident -slips past it into the generic reference path and previously hit the -`panic("should never lookup PkgName ...")` assertion in `lookup.go`. The visitor -now skips bare `*types.PkgName` references instead of crashing. +`var _ = sort` is syntactically valid Go but ill-typed; the compiler rejects it +with `use of package sort not in selector`. The parser still accepts it and the +type checker, run in best-effort mode by `packages.Load`, still records +`info.Uses[sort] = *types.PkgName`. + +Well-typed code routes such uses through the `*ast.SelectorExpr` handler in +`visitor_file.go`; a bare ident slips past it into the generic reference path +and previously hit the `panic("should never lookup PkgName ...")` assertion in +`lookup.go`. The visitor now skips bare `*types.PkgName` references instead of +crashing. From f9522229c2278af70a3e9de2197ccb0073ad398c Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 20 May 2026 14:07:53 +0200 Subject: [PATCH 3/3] flake: exclude pr261 input from goimports check pr261's repro keeps an intentionally-unused 'sort' import to reproduce the bare PkgName panic. goimports would strip the import and break the repro, so skip the directory the same way snapshots/output is skipped. --- flake.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flake.nix b/flake.nix index f9013df..dccf7a4 100644 --- a/flake.nix +++ b/flake.nix @@ -82,8 +82,11 @@ bad=$( # Snapshot outputs are generated with modified # indentation for alignment with annotations. + # pr261's input intentionally keeps an "unused" import + # to reproduce a panic on a bare PkgName ident. find . -name '*.go' \ -not -path '*/testdata/snapshots/output/*' \ + -not -path '*/testdata/snapshots/input/pr261/*' \ -exec ${pkgs.gotools}/bin/goimports -l {} + ) if [ -n "$bad" ]; then