diff options
| author | Mark Freeman <mark@golang.org> | 2026-03-30 16:32:37 -0400 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-31 16:41:58 -0700 |
| commit | 328950b13c79cbc3ce429318583385e96a710389 (patch) | |
| tree | 48cfeefbb593fb4d0420df60a1dd4b078685be8b /src/cmd/compile/internal/noder | |
| parent | 9cd372147e0bf75afdb700177b36ef984b533a54 (diff) | |
| download | go-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.go | 53 |
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 |
