aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal
diff options
context:
space:
mode:
authorMark Freeman <mark@golang.org>2026-04-03 11:52:55 -0400
committerMark Freeman <mark@golang.org>2026-04-03 14:44:10 -0700
commitf4b87f314dd7a890e9d3b42d7d6427cc7f51f9a2 (patch)
tree5f6aef0b793f65a9f4711cd8b3157c475c57a794 /src/cmd/compile/internal
parent583ed06a2b82cf7437b37b2fc1fd2c772d7de420 (diff)
downloadgo-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')
-rw-r--r--src/cmd/compile/internal/noder/writer.go91
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.