cmd/compile: treat constants to type parameter conversion as non-constant in Unified IR

Fixes #54307

Change-Id: Idcbdb3b1cf7c7fd147cc079659f29a9b5d17e6e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/421874
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Cuong Manh Le 2022-08-06 20:56:39 +07:00
parent 98f5152368
commit 1519729c6a
4 changed files with 40 additions and 4 deletions

View File

@ -251,3 +251,8 @@ func idealType(tv types2.TypeAndValue) types2.Type {
} }
return typ return typ
} }
func isTypeParam(t types2.Type) bool {
_, ok := t.(*types2.TypeParam)
return ok
}

View File

@ -2019,6 +2019,7 @@ func (r *reader) expr() (res ir.Node) {
typ := r.typ() typ := r.typ()
pos := r.pos() pos := r.pos()
typeWord, srcRType := r.convRTTI(pos) typeWord, srcRType := r.convRTTI(pos)
dstTypeParam := r.Bool()
x := r.expr() x := r.expr()
// TODO(mdempsky): Stop constructing expressions of untyped type. // TODO(mdempsky): Stop constructing expressions of untyped type.
@ -2034,12 +2035,21 @@ func (r *reader) expr() (res ir.Node) {
base.ErrorExit() // harsh, but prevents constructing invalid IR base.ErrorExit() // harsh, but prevents constructing invalid IR
} }
n := ir.NewConvExpr(pos, ir.OCONV, typ, x) ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
n.TypeWord, n.SrcRType = typeWord, srcRType ce.TypeWord, ce.SrcRType = typeWord, srcRType
if implicit { if implicit {
n.SetImplicit(true) ce.SetImplicit(true)
} }
return typecheck.Expr(n) n := typecheck.Expr(ce)
// spec: "If the type is a type parameter, the constant is converted
// into a non-constant value of the type parameter."
if dstTypeParam && ir.IsConstNode(n) {
// Wrap in an OCONVNOP node to ensure result is non-constant.
n = Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, n.Type(), n))
n.SetTypecheck(1)
}
return n
} }
} }

View File

@ -1692,6 +1692,7 @@ func (w *writer) expr(expr syntax.Expr) {
w.typ(tv.Type) w.typ(tv.Type)
w.pos(expr) w.pos(expr)
w.convRTTI(w.p.typeOf(expr.ArgList[0]), tv.Type) w.convRTTI(w.p.typeOf(expr.ArgList[0]), tv.Type)
w.Bool(isTypeParam(tv.Type))
w.expr(expr.ArgList[0]) w.expr(expr.ArgList[0])
break break
} }
@ -1854,6 +1855,7 @@ func (w *writer) implicitConvExpr(pos poser, dst types2.Type, expr syntax.Expr)
w.typ(dst) w.typ(dst)
w.pos(pos) w.pos(pos)
w.convRTTI(src, dst) w.convRTTI(src, dst)
w.Bool(isTypeParam(dst))
// fallthrough // fallthrough
} }
w.expr(expr) w.expr(expr)

View File

@ -0,0 +1,19 @@
// compile
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
func f[Int int, Uint uint]() {
_ = uint(Int(-1))
_ = uint(Uint(0) - 1)
}
func g[String string]() {
_ = String("")[100]
}
var _ = f[int, uint]
var _ = g[string]