[tools] gopls/internal/cache/methodsets: fix panic on types with generic methods

4 views
Skip to first unread message

Koichi Shiraishi (zchee) (Gerrit)

unread,
Jun 4, 2026, 1:57:35 AM (3 days ago) Jun 4
to goph...@pubsubhelper.golang.org, Alan Donovan, golang-co...@googlegroups.com

Koichi Shiraishi (zchee) has uploaded the change for review

Commit message

gopls/internal/cache/methodsets: fix panic on types with generic methods

CL 776140 started skipping generic methods when building the method-set
index, as they do not participate in interface satisfaction. But
methodSetInfo allocated the method slice at the full method-set length
and assigned each entry by index, so a skipped method left a nil
*gobMethod hole in the slice.

A type that has a generic method alongside an ordinary one is still
recorded in the index, because the ordinary method gives it a non-zero
mask. The nil hole therefore survives into the serialized index, and an
Implementation (or References) query that later iterates the type's
methods in implements dereferences the nil pointer and crashes gopls.

Build the slice with append, preallocating capacity but not length, so
that skipped methods leave no holes.

Also add a cross-package implementation marker test over a type with
both a generic and an ordinary method, which panics without this fix.

Updates golang/go#77549
Change-Id: I5dc54df8e24031a4d12002f791715426f1f3c18d

Change diff

diff --git a/gopls/internal/cache/methodsets/methodsets.go b/gopls/internal/cache/methodsets/methodsets.go
index 8be9c9d..5936bd1 100644
--- a/gopls/internal/cache/methodsets/methodsets.go
+++ b/gopls/internal/cache/methodsets/methodsets.go
@@ -392,7 +392,9 @@
var mask uint64
tricky := false
var buf []byte
- methods := make([]*gobMethod, mset.Len())
+ // Preallocate capacity, but grow by append so that skipped
+ // (generic) methods leave no nil holes in the slice.
+ methods := make([]*gobMethod, 0, mset.Len())
for i := 0; i < mset.Len(); i++ {
m := mset.At(i).Obj().(*types.Func)
// Generic methods do not participate in interface satisfaction.
@@ -406,9 +408,10 @@
}
buf = append(append(buf[:0], id...), fp...)
sum := crc32.ChecksumIEEE(buf)
- methods[i] = &gobMethod{ID: id, Fingerprint: fp, Sum: sum, Tricky: isTricky}
+ gm := &gobMethod{ID: id, Fingerprint: fp, Sum: sum, Tricky: isTricky}
+ methods = append(methods, gm)
if setIndexInfo != nil {
- setIndexInfo(methods[i], m) // set Position, PkgPath, ObjectPath
+ setIndexInfo(gm, m) // set Position, PkgPath, ObjectPath
}
mask |= 1 << uint64(((sum>>24)^(sum>>16)^(sum>>8)^sum)&0x3f)
}
diff --git a/gopls/internal/test/marker/testdata/implementation/genericmethods-mixed.txt b/gopls/internal/test/marker/testdata/implementation/genericmethods-mixed.txt
new file mode 100644
index 0000000..e1639d6
--- /dev/null
+++ b/gopls/internal/test/marker/testdata/implementation/genericmethods-mixed.txt
@@ -0,0 +1,42 @@
+Regression test for a crash in the method-set index when a type has
+both an ordinary method and a generic method (Go 1.27).
+
+Generic methods are skipped while building the method-set index (they
+do not participate in interface satisfaction), but the surrounding type
+is still indexed because its ordinary method gives it a non-zero mask.
+A bug once pre-sized the method slice to the full method-set length and
+filled it by index, so skipping the generic method left a nil hole;
+iterating those methods during a search panicked with a nil-pointer
+dereference.
+
+The query and its implementer are deliberately in different packages so
+that the search goes through the serialized methodsets index (the path
+that held the nil hole), not the go/types-based local path.
+
+See the fix in gopls/internal/cache/methodsets, follow-up to golang/go#77549.
+
+-- flags --
+-min_go=go1.27
+
+-- go.mod --
+module example.com
+go 1.27
+
+-- a/a.go --
+package a
+
+// C has an ordinary method G, so it is recorded in the method-set
+// index, and a generic method F, which is skipped during indexing and
+// must not leave a nil hole. C implements b.I via G alone.
+type C struct{} //@loc(C, "C"), implementation("C", I)
+
+func (C) G(int) {}
+
+func (C) F[T any](T) {}
+
+-- b/b.go --
+package b
+
+type I interface { //@loc(I, "I"), implementation("I", C)
+ G(int)
+}

Change information

Files:
  • M gopls/internal/cache/methodsets/methodsets.go
  • A gopls/internal/test/marker/testdata/implementation/genericmethods-mixed.txt
Change size: M
Delta: 2 files changed, 48 insertions(+), 3 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: tools
Gerrit-Branch: master
Gerrit-Change-Id: I5dc54df8e24031a4d12002f791715426f1f3c18d
Gerrit-Change-Number: 786840
Gerrit-PatchSet: 1
Gerrit-Owner: Koichi Shiraishi (zchee) <zche...@gmail.com>
Gerrit-CC: Alan Donovan <adon...@google.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Alan Donovan (Gerrit)

unread,
Jun 4, 2026, 4:00:16 PM (2 days ago) Jun 4
to Koichi Shiraishi (zchee), goph...@pubsubhelper.golang.org, Hongxiang Jiang, golang-co...@googlegroups.com
Attention needed from Koichi Shiraishi (zchee)

Alan Donovan voted and added 1 comment

Votes added by Alan Donovan

Hold+1

1 comment

Patchset-level comments
File-level comment, Patchset 1 (Latest):
Alan Donovan . resolved

Thanks for tackling this. However, I don't think this is the right fix. Generic methods are not in the method set of a type; therefore the appropriate fix is in types.MethodSet.

Open in Gerrit

Related details

Attention is currently required from:
  • Koichi Shiraishi (zchee)
Submit Requirements:
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Holds
    • requirement satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: tools
    Gerrit-Branch: master
    Gerrit-Change-Id: I5dc54df8e24031a4d12002f791715426f1f3c18d
    Gerrit-Change-Number: 786840
    Gerrit-PatchSet: 1
    Gerrit-Owner: Koichi Shiraishi (zchee) <zche...@gmail.com>
    Gerrit-Reviewer: Alan Donovan <adon...@google.com>
    Gerrit-CC: Hongxiang Jiang <hxj...@golang.org>
    Gerrit-Attention: Koichi Shiraishi (zchee) <zche...@gmail.com>
    Gerrit-Comment-Date: Thu, 04 Jun 2026 20:00:12 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Koichi Shiraishi (zchee) (Gerrit)

    unread,
    Jun 4, 2026, 4:47:51 PM (2 days ago) Jun 4
    to goph...@pubsubhelper.golang.org, Mark Freeman, Alan Donovan, Hongxiang Jiang, golang-co...@googlegroups.com
    Attention needed from Alan Donovan

    Koichi Shiraishi (zchee) added 1 comment

    Patchset-level comments
    Alan Donovan . unresolved

    Thanks for tackling this. However, I don't think this is the right fix. Generic methods are not in the method set of a type; therefore the appropriate fix is in types.MethodSet.

    Koichi Shiraishi (zchee)

    Perhaps this is due to the influence of https://go-review.googlesource.com/c/go/+/785740 revert?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Alan Donovan
    Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Holds
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement is not satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: tools
      Gerrit-Branch: master
      Gerrit-Change-Id: I5dc54df8e24031a4d12002f791715426f1f3c18d
      Gerrit-Change-Number: 786840
      Gerrit-PatchSet: 1
      Gerrit-Owner: Koichi Shiraishi (zchee) <zche...@gmail.com>
      Gerrit-Reviewer: Alan Donovan <adon...@google.com>
      Gerrit-CC: Hongxiang Jiang <hxj...@golang.org>
      Gerrit-CC: Mark Freeman <markf...@google.com>
      Gerrit-Attention: Alan Donovan <adon...@google.com>
      Gerrit-Comment-Date: Thu, 04 Jun 2026 20:47:40 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Alan Donovan <adon...@google.com>
      unsatisfied_requirement
      open
      diffy

      Alan Donovan (Gerrit)

      unread,
      Jun 4, 2026, 5:37:18 PM (2 days ago) Jun 4
      to Koichi Shiraishi (zchee), goph...@pubsubhelper.golang.org, Mark Freeman, Hongxiang Jiang, golang-co...@googlegroups.com
      Attention needed from Koichi Shiraishi (zchee)

      Alan Donovan added 1 comment

      Patchset-level comments
      Alan Donovan . unresolved

      Thanks for tackling this. However, I don't think this is the right fix. Generic methods are not in the method set of a type; therefore the appropriate fix is in types.MethodSet.

      Koichi Shiraishi (zchee)

      Perhaps this is due to the influence of https://go-review.googlesource.com/c/go/+/785740 revert?

      Alan Donovan

      Yes, we need to un-revert that change, but it was (I think) unfairly blamed for a bug in the api checker, which assumes that generic methods can be found in types.MethodSet; it needs to be fixed.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Koichi Shiraishi (zchee)
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Holds
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement is not satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: tools
      Gerrit-Branch: master
      Gerrit-Change-Id: I5dc54df8e24031a4d12002f791715426f1f3c18d
      Gerrit-Change-Number: 786840
      Gerrit-PatchSet: 1
      Gerrit-Owner: Koichi Shiraishi (zchee) <zche...@gmail.com>
      Gerrit-Reviewer: Alan Donovan <adon...@google.com>
      Gerrit-CC: Hongxiang Jiang <hxj...@golang.org>
      Gerrit-CC: Mark Freeman <markf...@google.com>
      Gerrit-Attention: Koichi Shiraishi (zchee) <zche...@gmail.com>
      Gerrit-Comment-Date: Thu, 04 Jun 2026 21:37:15 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Koichi Shiraishi (zchee) <zche...@gmail.com>
      Comment-In-Reply-To: Alan Donovan <adon...@google.com>
      unsatisfied_requirement
      open
      diffy

      Koichi Shiraishi (zchee) (Gerrit)

      unread,
      Jun 6, 2026, 7:36:56 AM (18 hours ago) Jun 6
      to goph...@pubsubhelper.golang.org, Mark Freeman, Alan Donovan, Hongxiang Jiang, golang-co...@googlegroups.com
      Attention needed from Alan Donovan

      Koichi Shiraishi (zchee) added 1 comment

      Patchset-level comments
      Alan Donovan . unresolved

      Thanks for tackling this. However, I don't think this is the right fix. Generic methods are not in the method set of a type; therefore the appropriate fix is in types.MethodSet.

      Koichi Shiraishi (zchee)

      Perhaps this is due to the influence of https://go-review.googlesource.com/c/go/+/785740 revert?

      Alan Donovan

      Yes, we need to un-revert that change, but it was (I think) unfairly blamed for a bug in the api checker, which assumes that generic methods can be found in types.MethodSet; it needs to be fixed.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Alan Donovan
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Holds
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement is not satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: tools
      Gerrit-Branch: master
      Gerrit-Change-Id: I5dc54df8e24031a4d12002f791715426f1f3c18d
      Gerrit-Change-Number: 786840
      Gerrit-PatchSet: 1
      Gerrit-Owner: Koichi Shiraishi (zchee) <zche...@gmail.com>
      Gerrit-Reviewer: Alan Donovan <adon...@google.com>
      Gerrit-CC: Hongxiang Jiang <hxj...@golang.org>
      Gerrit-CC: Mark Freeman <markf...@google.com>
      Gerrit-Attention: Alan Donovan <adon...@google.com>
      Gerrit-Comment-Date: Sat, 06 Jun 2026 11:36:47 +0000
      unsatisfied_requirement
      open
      diffy
      Reply all
      Reply to author
      Forward
      0 new messages