diff options
| author | Mark Freeman <mark@golang.org> | 2026-04-03 11:52:55 -0400 |
|---|---|---|
| committer | Mark Freeman <mark@golang.org> | 2026-04-03 14:44:10 -0700 |
| commit | f4b87f314dd7a890e9d3b42d7d6427cc7f51f9a2 (patch) | |
| tree | 5f6aef0b793f65a9f4711cd8b3157c475c57a794 /src/cmd/compile/internal/noder | |
| parent | 583ed06a2b82cf7437b37b2fc1fd2c772d7de420 (diff) | |
| download | go-f4b87f314dd7a890e9d3b42d7d6427cc7f51f9a2.tar.xz | |
cmd/compile/internal/noder: recognize generic method instantiation
This change slightly extends expression traversal to recognize
explicit instantiation of generic methods. The relevant MethodVal
and MethodExpr snippets are extracted into helper functions, since
they are needed in two places.
Change-Id: I85d49d89f2422fa4c2d09de28fb6552f171a2a1f
Reviewed-on: https://go-review.googlesource.com/c/go/+/762560
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 91 |
1 files changed, 60 insertions, 31 deletions
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index c4c7458a27..f01d26122e 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1959,41 +1959,30 @@ func (w *writer) expr(expr syntax.Expr) { w.selector(sel.Obj()) case types2.MethodVal: - w.Code(exprMethodVal) - typ := w.recvExpr(expr, sel) - w.pos(expr) - w.methodExpr(expr, typ, sel) + w.methVal(expr, sel) case types2.MethodExpr: - w.Code(exprMethodExpr) - - tv := w.p.typeAndValue(expr.X) - assert(tv.IsType()) - - index := sel.Index() - implicits := index[:len(index)-1] - - typ := tv.Type - w.typ(typ) - - w.Len(len(implicits)) - for _, ix := range implicits { - w.Len(ix) - typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type() - } - - recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type() - if w.Bool(isPtrTo(typ, recv)) { // need deref - typ = recv - } else if w.Bool(isPtrTo(recv, typ)) { // need addr - typ = recv - } - - w.pos(expr) - w.methodExpr(expr, typ, sel) + w.methExpr(expr, sel) } case *syntax.IndexExpr: + // might be explicit instantiation of a generic method + if selector, ok := expr.X.(*syntax.SelectorExpr); ok { + if sel, ok := w.p.info.Selections[selector]; ok { + switch sel.Kind() { + default: + w.p.fatalf(selector, "unexpected selection kind: %v", sel.Kind()) + case types2.FieldVal: + // not a method + case types2.MethodVal: + w.methVal(selector, sel) + return + case types2.MethodExpr: + w.methExpr(selector, sel) + return + } + } + } _ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation xtyp := w.p.typeOf(expr.X) @@ -2165,7 +2154,11 @@ func (w *writer) expr(expr syntax.Expr) { writeFunExpr := func() { fun := syntax.Unparen(expr.Fun) - if selector, ok := fun.(*syntax.SelectorExpr); ok { + expr := fun + if idx, ok := expr.(*syntax.IndexExpr); ok { + expr = idx.X + } + if selector, ok := expr.(*syntax.SelectorExpr); ok { if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal { w.Bool(true) // method call typ := w.recvExpr(selector, sel) @@ -2219,6 +2212,42 @@ func (w *writer) optExpr(expr syntax.Expr) { } } +func (w *writer) methVal(expr *syntax.SelectorExpr, sel *types2.Selection) { + w.Code(exprMethodVal) + typ := w.recvExpr(expr, sel) + w.pos(expr) + w.methodExpr(expr, typ, sel) +} + +func (w *writer) methExpr(expr *syntax.SelectorExpr, sel *types2.Selection) { + w.Code(exprMethodExpr) + + tv := w.p.typeAndValue(expr.X) + assert(tv.IsType()) + + index := sel.Index() + implicits := index[:len(index)-1] + + typ := tv.Type + w.typ(typ) + + w.Len(len(implicits)) + for _, ix := range implicits { + w.Len(ix) + typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type() + } + + recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type() + if w.Bool(isPtrTo(typ, recv)) { // need deref + typ = recv + } else if w.Bool(isPtrTo(recv, typ)) { // need addr + typ = recv + } + + w.pos(expr) + w.methodExpr(expr, typ, sel) +} + // recvExpr writes out expr.X, but handles any implicit addressing, // dereferencing, and field selections appropriate for the method // selection. |
