]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: call types.CheckSize() in g.typ()
authorDan Scales <danscales@google.com>
Thu, 11 Mar 2021 03:28:28 +0000 (19:28 -0800)
committerDan Scales <danscales@google.com>
Fri, 12 Mar 2021 00:52:00 +0000 (00:52 +0000)
Restore code to call types.CheckSize() in g.typ(). There are certain
cases (involving maps) where we need to do CheckSize here. In general,
the old typechecker calls CheckSize() a lot, and we want to eliminate
calling it eventually, so should get do types.CheckSize() when we create
a new concrete type.

However, the test typeparams/cons.go does not work with just calling
types.CheckSize() in g.typ() (which is why I disabled the calls
originally). The reason is that g.typ() is called recursively within
types.go, so it can be called on a partially-created recursive type,
which leads to an error in CheckSize(). So, we need to call CheckSize()
only on fully-created top-level types. So, I divided typ() into typ()
and typ1(), where typ() is now the external entry point, and typ1() is
called within types.go. Now, typ() can call CheckSize() safely.

I also added in an extra condition - we do not currently need to call
CheckSize() on non-fully-instantiated types, since they will not make it
to the backend.  That could change a bit with dictionaries.

Fixes #44895

Change-Id: I783aa7d2999dd882ddbd99a7c19a6ff6ee420102
Reviewed-on: https://go-review.googlesource.com/c/go/+/300989
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Dan Scales <danscales@google.com>
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/noder/types.go

index 96bf75d594eb36c47d114b4d54a238c3f39f7e62..58b7262455a08323cfde4109438306c4f81eb725 100644 (file)
@@ -30,6 +30,23 @@ func (g *irgen) pkg(pkg *types2.Package) *types.Pkg {
 // typ converts a types2.Type to a types.Type, including caching of previously
 // translated types.
 func (g *irgen) typ(typ types2.Type) *types.Type {
+       res := g.typ1(typ)
+
+       // Calculate the size for all concrete types seen by the frontend. The old
+       // typechecker calls CheckSize() a lot, and we want to eliminate calling
+       // it eventually, so we should do it here instead. We only call it for
+       // top-level types (i.e. we do it here rather in typ1), to make sure that
+       // recursive types have been fully constructed before we call CheckSize.
+       if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() {
+               types.CheckSize(res)
+       }
+       return res
+}
+
+// typ1 is like typ, but doesn't call CheckSize, since it may have only
+// constructed part of a recursive type. Should not be called from outside this
+// file (g.typ is the "external" entry point).
+func (g *irgen) typ1(typ types2.Type) *types.Type {
        // Cache type2-to-type mappings. Important so that each defined generic
        // type (instantiated or not) has a single types.Type representation.
        // Also saves a lot of computation and memory by avoiding re-translating
@@ -38,13 +55,6 @@ func (g *irgen) typ(typ types2.Type) *types.Type {
        if !ok {
                res = g.typ0(typ)
                g.typs[typ] = res
-
-               // Ensure we calculate the size for all concrete types seen by
-               // the frontend. This is another heavy hammer for something that
-               // should really be the backend's responsibility instead.
-               //if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() {
-               //      types.CheckSize(res)
-               //}
        }
        return res
 }
@@ -121,12 +131,12 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
                        // instantiated type.
                        rparams := make([]*types.Type, len(typ.TArgs()))
                        for i, targ := range typ.TArgs() {
-                               rparams[i] = g.typ(targ)
+                               rparams[i] = g.typ1(targ)
                        }
                        ntyp.SetRParams(rparams)
                        //fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
 
-                       ntyp.SetUnderlying(g.typ(typ.Underlying()))
+                       ntyp.SetUnderlying(g.typ1(typ.Underlying()))
                        g.fillinMethods(typ, ntyp)
                        return ntyp
                }
@@ -137,23 +147,23 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
                return obj.Type()
 
        case *types2.Array:
-               return types.NewArray(g.typ(typ.Elem()), typ.Len())
+               return types.NewArray(g.typ1(typ.Elem()), typ.Len())
        case *types2.Chan:
-               return types.NewChan(g.typ(typ.Elem()), dirs[typ.Dir()])
+               return types.NewChan(g.typ1(typ.Elem()), dirs[typ.Dir()])
        case *types2.Map:
-               return types.NewMap(g.typ(typ.Key()), g.typ(typ.Elem()))
+               return types.NewMap(g.typ1(typ.Key()), g.typ1(typ.Elem()))
        case *types2.Pointer:
-               return types.NewPtr(g.typ(typ.Elem()))
+               return types.NewPtr(g.typ1(typ.Elem()))
        case *types2.Signature:
                return g.signature(nil, typ)
        case *types2.Slice:
-               return types.NewSlice(g.typ(typ.Elem()))
+               return types.NewSlice(g.typ1(typ.Elem()))
 
        case *types2.Struct:
                fields := make([]*types.Field, typ.NumFields())
                for i := range fields {
                        v := typ.Field(i)
-                       f := types.NewField(g.pos(v), g.selector(v), g.typ(v.Type()))
+                       f := types.NewField(g.pos(v), g.selector(v), g.typ1(v.Type()))
                        f.Note = typ.Tag(i)
                        if v.Embedded() {
                                f.Embedded = 1
@@ -167,7 +177,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
                for i := range embeddeds {
                        // TODO(mdempsky): Get embedding position.
                        e := typ.EmbeddedType(i)
-                       embeddeds[i] = types.NewField(src.NoXPos, nil, g.typ(e))
+                       embeddeds[i] = types.NewField(src.NoXPos, nil, g.typ1(e))
                }
 
                methods := make([]*types.Field, typ.NumExplicitMethods())
@@ -190,7 +200,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
 
                // TODO(danscales): we don't currently need to use the bounds
                // anywhere, so eventually we can probably remove.
-               bound := g.typ(typ.Bound())
+               bound := g.typ1(typ.Bound())
                *tp.Methods() = *bound.Methods()
                return tp
 
@@ -205,8 +215,6 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
                        fields[i] = g.param(typ.At(i))
                }
                t := types.NewStruct(types.LocalPkg, fields)
-               //types.CheckSize(t)
-               // Can only set after doing the types.CheckSize()
                t.StructType().Funarg = types.FunargResults
                return t
 
@@ -223,7 +231,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
        if typ.NumMethods() != 0 {
                targs := make([]ir.Node, len(typ.TArgs()))
                for i, targ := range typ.TArgs() {
-                       targs[i] = ir.TypeNode(g.typ(targ))
+                       targs[i] = ir.TypeNode(g.typ1(targ))
                }
 
                methods := make([]*types.Field, typ.NumMethods())
@@ -256,7 +264,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
                                        rparams := types2.AsSignature(m.Type()).RParams()
                                        tparams := make([]*types.Field, len(rparams))
                                        for i, rparam := range rparams {
-                                               tparams[i] = types.NewField(src.NoXPos, nil, g.typ(rparam.Type()))
+                                               tparams[i] = types.NewField(src.NoXPos, nil, g.typ1(rparam.Type()))
                                        }
                                        assert(len(tparams) == len(targs))
                                        subst := &subster{
@@ -286,7 +294,7 @@ func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type
        tparams := make([]*types.Field, len(tparams2))
        for i := range tparams {
                tp := tparams2[i]
-               tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ(tp.Type()))
+               tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ1(tp.Type()))
        }
 
        do := func(typ *types2.Tuple) []*types.Field {
@@ -306,7 +314,7 @@ func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type
 }
 
 func (g *irgen) param(v *types2.Var) *types.Field {
-       return types.NewField(g.pos(v), g.sym(v), g.typ(v.Type()))
+       return types.NewField(g.pos(v), g.sym(v), g.typ1(v.Type()))
 }
 
 func (g *irgen) sym(obj types2.Object) *types.Sym {