diff options
author | Dan Scales <danscales@google.com> | 2021-07-21 16:23:17 -0700 |
---|---|---|
committer | Dan Scales <danscales@google.com> | 2021-07-23 20:57:41 +0000 |
commit | 12866bd8ea13e43bc5995f58cdeb67ffd64a1c8c (patch) | |
tree | d57f6807409e9814c6020f1628487adf6fc8b516 /src/cmd/compile/internal/noder/helpers.go | |
parent | 4cdc65d32a3f0378cc508e8eb395063b83683fd4 (diff) | |
download | go-git-12866bd8ea13e43bc5995f58cdeb67ffd64a1c8c.tar.gz |
[dev.typeparams] Add CONVIFACE nodes in noder2, where possible
Changes to add CONVIFACE nodes where possible in noder2, even when the
args are typeparams. The transformation to insert a CONVIFACE node can
usually happen when there an obvious assignment/conversion to an
interface type from a non-interface type. So, we now do this
tranformation for:
- direct conversions to an interface type
- function arguments that are implicitly converted to an interface
based on the parameter types.
- EQ/NE comparison of an interface and a non-interface
With this change, we can remove some special case checks for CONVIFACE
nodes after transformation in node(), and instead just have the one
check in the CONVIFACE check.
Change-Id: I7cf2ef920aebf9e5553210aeaf19f344e128ca62
Reviewed-on: https://go-review.googlesource.com/c/go/+/336992
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/noder/helpers.go')
-rw-r--r-- | src/cmd/compile/internal/noder/helpers.go | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 15b3277908..2b00a9d7a6 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -116,9 +116,12 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) if fun.Op() == ir.OTYPE { // Actually a type conversion, not a function call. - if fun.Type().HasTParam() || args[0].Type().HasTParam() { - // For type params, don't typecheck until we actually know - // the type. + if !fun.Type().IsInterface() && + (fun.Type().HasTParam() || args[0].Type().HasTParam()) { + // For type params, we can transform if fun.Type() is known + // to be an interface (in which case a CONVIFACE node will be + // inserted). Otherwise, don't typecheck until we actually + // know the type. return typed(typ, n) } typed(typ, n) @@ -169,11 +172,15 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } 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. + // If the fun arg is or has a type param, we can't do all the + // transformations, since we may not have needed properties yet. + // (e.g. number of return values, etc). However, if we do have the + // function type (even though it is parameterized), then can add in + // any needed CONVIFACE nodes. We can't do anything if fun is a type + // param (which is probably described by a structural constraint) + if fun.Type().Kind() == types.TFUNC { + typecheckaste(ir.OCALL, fun, n.IsDDD, fun.Type().Params(), n.Args, true) + } return typed(typ, n) } @@ -203,11 +210,18 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node { n := ir.NewBinaryExpr(pos, op, x, y) if x.Type().HasTParam() || y.Type().HasTParam() { - // Delay transformCompare() if either arg has a type param, since - // it needs to know the exact types to decide on any needed conversions. - n.SetType(typ) - n.SetTypecheck(3) - return n + xIsInt := x.Type().IsInterface() + yIsInt := y.Type().IsInterface() + if !(xIsInt && !yIsInt || !xIsInt && yIsInt) { + // If either arg is a type param, then we can still do the + // transformCompare() if we know that one arg is an interface + // and the other is not. Otherwise, we delay + // transformCompare(), since it needs to know the exact types + // to decide on any needed conversions. + n.SetType(typ) + n.SetTypecheck(3) + return n + } } typed(typ, n) transformCompare(n) |