diff options
| author | Robert Griesemer <gri@golang.org> | 2021-09-22 09:55:10 -0700 |
|---|---|---|
| committer | Robert Griesemer <gri@golang.org> | 2021-09-28 16:36:22 +0000 |
| commit | 73418bca347c94560a6cb605d8eb393b56941446 (patch) | |
| tree | 0da0a14c7f7d5fa15dd3972d928ca987d47e9958 /src/cmd/compile/internal/noder | |
| parent | 583eeaae509a01cc50955c4174044b9dac539ff6 (diff) | |
| download | go-73418bca347c94560a6cb605d8eb393b56941446.tar.xz | |
cmd/compile/internal/types2: record all instances, not just inferred instances
This is a port of CL 349629 from go/types to types2, adjusted to
make it work for types2. It also includes the necessary compiler
changes, provided by mdempsky.
Change-Id: If8de174cee9c69df0d0642fcec1ee7622b7c3852
Reviewed-on: https://go-review.googlesource.com/c/go/+/351455
Trust: Robert Griesemer <gri@golang.org>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/expr.go | 79 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/irgen.go | 2 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/object.go | 21 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 57 |
4 files changed, 49 insertions, 110 deletions
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 9852ad964c..3dd7737c9f 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -114,86 +114,27 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.CallExpr: fun := g.expr(expr.Fun) - - // The key for the Inferred map is the CallExpr (if inferring - // types required the function arguments) or the IndexExpr below - // (if types could be inferred without the function arguments). - if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 { - // This is the case where inferring types required the - // types of the function arguments. - targs := make([]ir.Node, inferred.TArgs.Len()) - for i := range targs { - targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) - } - if fun.Op() == ir.OFUNCINST { - if len(fun.(*ir.InstExpr).Targs) < len(targs) { - // Replace explicit type args with the full list that - // includes the additional inferred type args. - // Substitute the type args for the type params in - // the generic function's type. - fun.(*ir.InstExpr).Targs = targs - newt := g.substType(fun.(*ir.InstExpr).X.Type(), fun.(*ir.InstExpr).X.Type().TParams(), targs) - typed(newt, fun) - } - } else { - // Create a function instantiation here, given there - // are only inferred type args (e.g. min(5,6), where - // min is a generic function). Substitute the type - // args for the type params in the generic function's - // type. - inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs) - newt := g.substType(fun.Type(), fun.Type().TParams(), targs) - typed(newt, inst) - fun = inst - } - - } return Call(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots) case *syntax.IndexExpr: - var targs []ir.Node - - if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 { - // This is the partial type inference case where the types - // can be inferred from other type arguments without using - // the types of the function arguments. - targs = make([]ir.Node, inferred.TArgs.Len()) - for i := range targs { - targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) - } - } else if _, ok := expr.Index.(*syntax.ListExpr); ok { - targs = g.exprList(expr.Index) - } else { - index := g.expr(expr.Index) - if index.Op() != ir.OTYPE { + args := unpackListExpr(expr.Index) + if len(args) == 1 { + tv, ok := g.info.Types[args[0]] + assert(ok) + if tv.IsValue() { // This is just a normal index expression - n := Index(pos, g.typ(typ), g.expr(expr.X), index) + n := Index(pos, g.typ(typ), g.expr(expr.X), g.expr(args[0])) if !g.delayTransform() { // transformIndex will modify n.Type() for OINDEXMAP. transformIndex(n) } return n } - // This is generic function instantiation with a single type - targs = []ir.Node{index} - } - // This is a generic function instantiation (e.g. min[int]). - // Generic type instantiation is handled in the type - // section of expr() above (using g.typ). - x := g.expr(expr.X) - if x.Op() != ir.ONAME || x.Type().Kind() != types.TFUNC { - panic("Incorrect argument for generic func instantiation") } - n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs) - newt := g.typ(typ) - // Substitute the type args for the type params in the uninstantiated - // function's type. If there aren't enough type args, then the rest - // will be inferred at the call node, so don't try the substitution yet. - if x.Type().TParams().NumFields() == len(targs) { - newt = g.substType(g.typ(typ), x.Type().TParams(), targs) - } - typed(newt, n) - return n + + // expr.Index is a list of type args, so we ignore it, since types2 has + // already provided this info with the Info.Instances map. + return g.expr(expr.X) case *syntax.SelectorExpr: // Qualified identifier. diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index e01e753a1d..c1a4f30f4a 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -59,7 +59,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { Selections: make(map[*syntax.SelectorExpr]*types2.Selection), Implicits: make(map[syntax.Node]types2.Object), Scopes: make(map[syntax.Node]*types2.Scope), - Inferred: make(map[syntax.Expr]types2.Inferred), + Instances: make(map[*syntax.Name]types2.Instance), // expand as needed } diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index 40c0b9cf42..37a995b519 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -22,9 +22,10 @@ func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) { return g.obj(obj), obj } -// use returns the Name node associated with the use of name. The returned node -// will have the correct type and be marked as typechecked. -func (g *irgen) use(name *syntax.Name) *ir.Name { +// use returns the Name or InstExpr node associated with the use of name, +// possibly instantiated by type arguments. The returned node will have +// the correct type and be marked as typechecked. +func (g *irgen) use(name *syntax.Name) ir.Node { obj2, ok := g.info.Uses[name] if !ok { base.FatalfAt(g.pos(name), "unknown name %v", name) @@ -36,6 +37,20 @@ func (g *irgen) use(name *syntax.Name) *ir.Name { obj.SetTypecheck(1) obj.SetType(obj.Defn.Type()) } + + if obj.Class == ir.PFUNC { + if inst, ok := g.info.Instances[name]; ok { + // This is the case where inferring types required the + // types of the function arguments. + targs := make([]ir.Node, inst.TypeArgs.Len()) + for i := range targs { + targs[i] = ir.TypeNode(g.typ(inst.TypeArgs.At(i))) + } + typ := g.substType(obj.Type(), obj.Type().TParams(), targs) + return typed(typ, ir.NewInstExpr(g.pos(name), ir.OFUNCINST, obj, targs)) + } + } + return obj } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 9edf5fc97a..47de992033 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -337,7 +337,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { w.typ(typ.Elem()) case *types2.Signature: - assert(typ.TypeParams() == nil) + base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ) w.code(typeSignature) w.signature(typ) @@ -1158,11 +1158,16 @@ func (w *writer) optLabel(label *syntax.Name) { func (w *writer) expr(expr syntax.Expr) { expr = unparen(expr) // skip parens; unneeded after typecheck - obj, targs := lookupObj(w.p.info, expr) + obj, inst := lookupObj(w.p.info, expr) + targs := inst.TypeArgs if tv, ok := w.p.info.Types[expr]; ok { // TODO(mdempsky): Be more judicious about which types are marked as "needed". - w.needType(tv.Type) + if inst.Type != nil { + w.needType(inst.Type) + } else { + w.needType(tv.Type) + } if tv.IsType() { w.code(exprType) @@ -1303,16 +1308,7 @@ func (w *writer) expr(expr syntax.Expr) { } } - if inf, ok := w.p.info.Inferred[expr]; ok { - obj, _ := lookupObj(w.p.info, expr.Fun) - assert(obj != nil) - - // As if w.expr(expr.Fun), but using inf.TArgs instead. - w.code(exprName) - w.obj(obj, inf.TArgs) - } else { - w.expr(expr.Fun) - } + w.expr(expr.Fun) w.bool(false) // not a method call (i.e., normal function call) } @@ -1756,31 +1752,17 @@ func isGlobal(obj types2.Object) bool { } // lookupObj returns the object that expr refers to, if any. If expr -// is an explicit instantiation of a generic object, then the type -// arguments are returned as well. -func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs *types2.TypeList) { +// is an explicit instantiation of a generic object, then the instance +// object is returned as well. +func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) { if index, ok := expr.(*syntax.IndexExpr); ok { - if inf, ok := info.Inferred[index]; ok { - targs = inf.TArgs - } else { - args := unpackListExpr(index.Index) - - if len(args) == 1 { - tv, ok := info.Types[args[0]] - assert(ok) - if tv.IsValue() { - return // normal index expression - } - } - - list := make([]types2.Type, len(args)) - for i, arg := range args { - tv, ok := info.Types[arg] - assert(ok) - assert(tv.IsType()) - list[i] = tv.Type + args := unpackListExpr(index.Index) + if len(args) == 1 { + tv, ok := info.Types[args[0]] + assert(ok) + if tv.IsValue() { + return // normal index expression } - targs = types2.NewTypeList(list) } expr = index.X @@ -1795,7 +1777,8 @@ func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs *t } if name, ok := expr.(*syntax.Name); ok { - obj, _ = info.Uses[name] + obj = info.Uses[name] + inst = info.Instances[name] } return } |
