diff options
Diffstat (limited to 'src')
| -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. |
