mirror of
https://github.com/golang/go
synced 2024-11-16 20:54:48 -07:00
[dev.unified] cmd/compile/internal/noder: wire RTTI for implicit conversions
This CL updates Unified IR to set the TypeWord and SrcRType fields on interface conversions, which will be necessary for dictionary support shortly. Change-Id: I9486b417f514ba4ec2ee8036194aa9ae3ad0ad93 Reviewed-on: https://go-review.googlesource.com/c/go/+/415575 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
c846fd8e13
commit
e376746e54
@ -1399,6 +1399,18 @@ func (r *reader) forStmt(label *types.Sym) ir.Node {
|
||||
}
|
||||
rang.Def = r.initDefn(rang, names)
|
||||
rang.Label = label
|
||||
|
||||
{
|
||||
keyType, valueType := rangeTypes(pos, x.Type())
|
||||
|
||||
if rang.Key != nil {
|
||||
rang.KeyTypeWord, rang.KeySrcRType = convRTTI(pos, rang.Key.Type(), keyType)
|
||||
}
|
||||
if rang.Value != nil {
|
||||
rang.ValueTypeWord, rang.ValueSrcRType = convRTTI(pos, rang.Value.Type(), valueType)
|
||||
}
|
||||
}
|
||||
|
||||
return rang
|
||||
}
|
||||
|
||||
@ -1414,6 +1426,28 @@ func (r *reader) forStmt(label *types.Sym) ir.Node {
|
||||
return stmt
|
||||
}
|
||||
|
||||
// rangeTypes returns the types of values produced by ranging over a
|
||||
// value of type typ.
|
||||
func rangeTypes(pos src.XPos, typ *types.Type) (key, value *types.Type) {
|
||||
switch typ.Kind() {
|
||||
default:
|
||||
base.FatalfAt(pos, "unexpected range type: %v", typ)
|
||||
panic("unreachable")
|
||||
case types.TPTR: // must be pointer to array
|
||||
typ = typ.Elem()
|
||||
base.AssertfAt(typ.Kind() == types.TARRAY, pos, "want array type, have %v", typ)
|
||||
fallthrough
|
||||
case types.TARRAY, types.TSLICE:
|
||||
return types.Types[types.TINT], typ.Elem()
|
||||
case types.TSTRING:
|
||||
return types.Types[types.TINT], types.RuneType
|
||||
case types.TMAP:
|
||||
return typ.Key(), typ.Elem()
|
||||
case types.TCHAN:
|
||||
return typ.Elem(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *reader) ifStmt() ir.Node {
|
||||
r.Sync(pkgbits.SyncIfStmt)
|
||||
r.openScope()
|
||||
@ -1803,14 +1837,42 @@ func (r *reader) expr() (res ir.Node) {
|
||||
base.ErrorExit() // harsh, but prevents constructing invalid IR
|
||||
}
|
||||
|
||||
n := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
|
||||
if implicit && n.Op() != ir.OLITERAL {
|
||||
n.(ImplicitNode).SetImplicit(true)
|
||||
n := ir.NewConvExpr(pos, ir.OCONV, typ, x)
|
||||
n.TypeWord, n.SrcRType = convRTTI(pos, typ, x.Type())
|
||||
if implicit {
|
||||
n.SetImplicit(true)
|
||||
}
|
||||
return n
|
||||
return typecheck.Expr(n)
|
||||
}
|
||||
}
|
||||
|
||||
// convRTTI returns the TypeWord and SrcRType expressions appropriate
|
||||
// for a conversion from src to dst.
|
||||
func convRTTI(pos src.XPos, dst, src *types.Type) (typeWord, srcRType ir.Node) {
|
||||
if !dst.IsInterface() {
|
||||
return
|
||||
}
|
||||
|
||||
// See reflectdata.ConvIfaceTypeWord.
|
||||
switch {
|
||||
case dst.IsEmptyInterface():
|
||||
if !src.IsInterface() {
|
||||
typeWord = reflectdata.TypePtrAt(pos, src) // direct eface construction
|
||||
}
|
||||
case !src.IsInterface():
|
||||
typeWord = reflectdata.ITabAddrAt(pos, src, dst) // direct iface construction
|
||||
default:
|
||||
typeWord = reflectdata.TypePtrAt(pos, dst) // convI2I
|
||||
}
|
||||
|
||||
// See reflectdata.ConvIfaceSrcRType.
|
||||
if !src.IsInterface() {
|
||||
srcRType = reflectdata.TypePtrAt(pos, src)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *reader) optExpr() ir.Node {
|
||||
if r.Bool() {
|
||||
return r.expr()
|
||||
@ -1841,7 +1903,10 @@ func (r *reader) multiExpr() []ir.Node {
|
||||
|
||||
res := ir.Node(tmp)
|
||||
if r.Bool() {
|
||||
res = typecheck.Expr(Implicit(ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)))
|
||||
n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
|
||||
n.TypeWord, n.SrcRType = convRTTI(pos, n.Type(), n.X.Type())
|
||||
n.SetImplicit(true)
|
||||
res = typecheck.Expr(n)
|
||||
}
|
||||
results[i] = res
|
||||
}
|
||||
|
@ -1260,11 +1260,6 @@ func (w *writer) forStmt(stmt *syntax.ForStmt) {
|
||||
|
||||
if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
|
||||
w.pos(rang)
|
||||
// TODO(mdempsky): For !rang.Def, we need to handle implicit
|
||||
// conversions; e.g., see #53328.
|
||||
//
|
||||
// This is tricky, because the assignments aren't introduced until
|
||||
// lowering in walk.
|
||||
w.assignList(rang.Lhs)
|
||||
w.expr(rang.X)
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user