1
0
mirror of https://github.com/golang/go synced 2024-11-12 00:20:22 -07:00

cmd/compile: call types.CheckSize() in g.typ()

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>
This commit is contained in:
Dan Scales 2021-03-10 19:28:28 -08:00
parent 7fc638d6f1
commit 71a6c13164

View 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 {