aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorMark Freeman <mark@golang.org>2026-03-30 16:32:37 -0400
committerGopher Robot <gobot@golang.org>2026-03-31 16:41:58 -0700
commit328950b13c79cbc3ce429318583385e96a710389 (patch)
tree48cfeefbb593fb4d0420df60a1dd4b078685be8b /src/cmd/compile/internal/noder
parent9cd372147e0bf75afdb700177b36ef984b533a54 (diff)
downloadgo-328950b13c79cbc3ce429318583385e96a710389.tar.xz
cmd/compile/internal/noder: encode dictionaries for generic methods
Generic methods have 2 sources of explicit type arguments-the receiver and the method itself. We simply concatenate these lists when constructing the dictionary. Change-Id: I8ba99fa7274b594941867e9bf6c2a22356c03e46 Reviewed-on: https://go-review.googlesource.com/c/go/+/761341 Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Mark Freeman <markfreeman@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/writer.go53
1 files changed, 30 insertions, 23 deletions
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 06264f5f87..0ee6a62c63 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -12,6 +12,7 @@ import (
"internal/buildcfg"
"internal/pkgbits"
"os"
+ "slices"
"strings"
"cmd/compile/internal/base"
@@ -2237,30 +2238,36 @@ func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *ty
}
if isConcreteMethod(sig) {
- if named, ok := types2.Unalias(deref2(recv)).(*types2.Named); ok {
- obj, targs := splitNamed(named)
- info := w.p.objInstIdx(obj, targs, w.dict)
-
- // Method on a derived receiver type. These can be handled by a
- // static call to the shaped method, but require dynamically
- // looking up the appropriate dictionary argument in the current
- // function's runtime dictionary.
- if w.p.hasImplicitTypeParams(obj) || info.anyDerived() {
- w.Bool(true) // dynamic subdictionary
- w.Len(w.dict.subdictIdx(info))
- return
- }
-
- // Method on a fully known receiver type. These can be handled
- // by a static call to the shaped method, and with a static
- // reference to the receiver type's dictionary.
- if len(targs) != 0 {
- w.Bool(false) // no dynamic subdictionary
- w.Bool(true) // static dictionary
- w.objInfo(info)
- return
- }
+ tname, tExplicits := splitNamed(types2.Unalias(deref2(recv)).(*types2.Named))
+ var info objInfo
+ if isGenericMethod(sig) {
+ // For generic methods, the shaped object is the method itself.
+ mExplicits := asTypeSlice(w.p.info.Instances[expr.Sel].TypeArgs)
+ info = w.p.objInstIdx(fun.Origin(), slices.Concat(tExplicits, mExplicits), w.dict)
+ } else {
+ // For non-generic concrete methods on generic types, the shaped object
+ // is the type. The method must be looked up on the type by name.
+ info = w.p.objInstIdx(tname, tExplicits, w.dict)
+ }
+ // We don't know all of the type arguments statically. These can be
+ // handled by a static call to the shaped method, but require
+ // dynamically looking up the appropriate dictionary argument
+ // in the current function's runtime dictionary.
+ if info.anyDerived() {
+ w.Bool(true) // dynamic subdictionary
+ w.Len(w.dict.subdictIdx(info))
+ return
+ }
+ // We know all of the type arguments statically. These can be handled
+ // by a static call to the shaped method, and with a static reference
+ // to either the receiver type's or method's dictionary (see above).
+ if len(info.explicits) > 0 {
+ w.Bool(false) // no dynamic subdictionary
+ w.Bool(true) // static dictionary
+ w.objInfo(info)
+ return
}
+ // no type arguments
}
w.Bool(false) // no dynamic subdictionary