cmd/compile: fix various small bugs related to type lists

Fix various small bugs related to delaying transformations due to type
params. Most of these relate to the need to delay a transformation when
an argument of an expression or statement has a type parameter that has
a structural constraint. The structural constraint implies the operation
should work, but the transformation can't happen until the actual value
of the type parameter is known.

 - delay transformations for send statements and return statements if
   any args/values have type params.

 - similarly, delay transformation of a call where the function arg has
   type parameters. This is mainly important for the case where the
   function arg is a pure type parameter, but has a structural
   constraint that requires it to be a function. Move the setting of
   n.Use to transformCall(), since we may not know how many return
   values there are until then, if the function arg is a type parameter.

 - set the type of unary expressions from the type2 type (as we do with
   most other expressions), since that works better with expressions
   with type params.

 - deal with these delayed transformations in subster.node() and convert
   the CALL checks to a switch statement.

 - make sure ir.CurFunc is set properly during stenciling, including
   closures (needed for transforming return statements during
   stenciling).

New test file typelist.go with tests for these cases.

Change-Id: I1b82f949d8cec47d906429209e846f4ebc8ec85e
Reviewed-on: https://go-review.googlesource.com/c/go/+/305729
Trust: Dan Scales <danscales@google.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Dan Scales 2021-03-29 08:28:01 -07:00
parent a95454b6f3
commit eeadfa2d38
6 changed files with 150 additions and 28 deletions

View file

@ -149,9 +149,13 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
}
}
n.Use = ir.CallUseExpr
if fun.Type().NumResults() == 0 {
n.Use = ir.CallUseStmt
if fun.Type().HasTParam() {
// If the fun arg is or has a type param, don't do any extra
// transformations, since we may not have needed properties yet
// (e.g. number of return values, etc). The type param is probably
// described by a structural constraint that requires it to be a
// certain function type, etc., but we don't want to analyze that.
return typed(typ, n)
}
if fun.Op() == ir.OXDOT {
@ -191,9 +195,9 @@ func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node {
return n
}
func Deref(pos src.XPos, x ir.Node) *ir.StarExpr {
func Deref(pos src.XPos, typ *types.Type, x ir.Node) *ir.StarExpr {
n := ir.NewStarExpr(pos, x)
typed(x.Type().Elem(), n)
typed(typ, n)
return n
}
@ -288,17 +292,22 @@ func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node {
return n
}
func Unary(pos src.XPos, op ir.Op, x ir.Node) ir.Node {
func Unary(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node) ir.Node {
switch op {
case ir.OADDR:
return Addr(pos, x)
case ir.ODEREF:
return Deref(pos, x)
return Deref(pos, typ, x)
}
typ := x.Type()
if op == ir.ORECV {
typ = typ.Elem()
if typ.IsFuncArgStruct() && typ.NumFields() == 2 {
// Remove the second boolean type (if provided by type2),
// since that works better with the rest of the compiler
// (which will add it back in later).
assert(typ.Field(1).Type.Kind() == types.TBOOL)
typ = typ.Field(0).Type
}
}
return typed(typ, ir.NewUnaryExpr(pos, op, x))
}