diff options
| author | Mark Freeman <mark@golang.org> | 2026-04-02 15:46:31 -0400 |
|---|---|---|
| committer | Mark Freeman <mark@golang.org> | 2026-04-03 10:10:30 -0700 |
| commit | 142f2376017887a3ed02dc1bc91542d39cfe2ecd (patch) | |
| tree | cca1d19148e45c9da7c725073a6ad014421632d7 /src | |
| parent | 5ecf12eedf00dec83cbfe29b1c5dc471e3fe5f94 (diff) | |
| download | go-142f2376017887a3ed02dc1bc91542d39cfe2ecd.tar.xz | |
cmd/compile/internal/noder: omit wrapper functions for generic methods
Emitting wrapper functions for generic methods is tricky for 2 reasons:
1. Existing downstream machinery expects that it can make certain
assumptions about a method if it sees a wrapper function. We
may violate those assumptions with generic method wrappers.
2. Signatures for generic methods are generic and hence cannot be
encoded using w.typ.
This has the slight downside of not using a statically computed
wrapper for generic methods and instead dynamically computing the
dictionary pointer. Thus, we miss out on a performance optimization
for generic methods for now. Code that does not use generic methods
is unaffected.
Change-Id: I72c626ef0f807c0cb54d8cf040250de8177303cc
Reviewed-on: https://go-review.googlesource.com/c/go/+/762382
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Mark Freeman <markfreeman@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 35 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 13 |
2 files changed, 35 insertions, 13 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index e0545a86db..e923d81bcd 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -2916,14 +2916,18 @@ func (r *reader) optExpr() ir.Node { // otherwise, they need to create their own wrapper. func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) { recv := r.typ() - sig0 := r.typ() + + var sig *types.Type + generic := r.Version().Has(pkgbits.GenericMethods) && r.Bool() + if !generic { + // Signature type to return (i.e., recv prepended to the method's + // normal parameters list). + sig = typecheck.NewMethodType(r.typ(), recv) + } + pos := r.pos() sym := r.selector() - // Signature type to return (i.e., recv prepended to the method's - // normal parameters list). - sig := typecheck.NewMethodType(sig0, recv) - if r.Bool() { // type parameter method expression idx := r.Len() word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx) @@ -2972,13 +2976,20 @@ func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) { base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn) } - // For statically known instantiations, we can take advantage of - // the stenciled wrapper. - base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv) - wrapperFn := typecheck.NewMethodExpr(pos, recv, sym) - base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig) - - return wrapperFn, shapedFn, dictPtr + if !generic { + // For statically known instantiations, we can take advantage of + // the stenciled wrapper. + base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv) + wrapperFn := typecheck.NewMethodExpr(pos, recv, sym) + base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig) + return wrapperFn, shapedFn, dictPtr + } else { + // Also statically known, but there is a good amount of existing + // machinery downstream which makes assumptions about method + // wrapper functions. It's safest not to emit them for now. + // TODO(mark): Emit wrapper functions for generic methods. + return nil, shapedFn, dictPtr + } } // Simple method expression; no dictionary needed. diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 5a549ea198..c4c7458a27 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -2276,7 +2276,18 @@ func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *ty sig := fun.Type().(*types2.Signature) w.typ(recv) - w.typ(sig) + + // only pass the signature if it's not a generic method + if isGenericMethod(sig) { + assert(w.Version().Has(pkgbits.GenericMethods)) + w.Bool(true) + } else { + if w.Version().Has(pkgbits.GenericMethods) { + w.Bool(false) + } + w.typ(sig) + } + w.pos(expr) w.selector(fun) |
