aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-09-22 09:55:10 -0700
committerRobert Griesemer <gri@golang.org>2021-09-28 16:36:22 +0000
commit73418bca347c94560a6cb605d8eb393b56941446 (patch)
tree0da0a14c7f7d5fa15dd3972d928ca987d47e9958 /src/cmd/compile/internal/noder
parent583eeaae509a01cc50955c4174044b9dac539ff6 (diff)
downloadgo-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.go79
-rw-r--r--src/cmd/compile/internal/noder/irgen.go2
-rw-r--r--src/cmd/compile/internal/noder/object.go21
-rw-r--r--src/cmd/compile/internal/noder/writer.go57
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
}