r.closeAnotherScope()
rang := ir.NewRangeStmt(pos, nil, nil, x, body)
+ if x.Type().IsMap() {
+ rang.RType = reflectdata.TypePtrAt(pos, x.Type())
+ }
if len(lhs) >= 1 {
rang.Key = lhs[0]
if len(lhs) >= 2 {
x := r.expr()
pos := r.pos()
index := r.expr()
- return typecheck.Expr(ir.NewIndexExpr(pos, x, index))
+ n := typecheck.Expr(ir.NewIndexExpr(pos, x, index))
+ switch n.Op() {
+ case ir.OINDEXMAP:
+ n := n.(*ir.IndexExpr)
+ n.RType = reflectdata.TypePtrAt(pos, x.Type())
+ }
+ return n
case exprSlice:
x := r.expr()
if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
+ assert.SrcRType = reflectdata.TypePtrAt(pos, x.Type())
assert.ITab = typ.ITab
return typed(typ.Type(), assert)
}
case ir.OANDAND, ir.OOROR:
return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
}
- return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
+ n := typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
+ switch n.Op() {
+ case ir.OEQ, ir.ONE:
+ n := n.(*ir.BinaryExpr)
+ if n.X.Type().IsInterface() != n.Y.Type().IsInterface() {
+ typ := n.X.Type()
+ if typ.IsInterface() {
+ typ = n.Y.Type()
+ }
+ n.RType = reflectdata.TypePtrAt(pos, typ)
+ }
+ }
+ return n
case exprCall:
fun := r.expr()
pos := r.pos()
args := r.exprs()
dots := r.Bool()
- return typecheck.Call(pos, fun, args, dots)
+ n := typecheck.Call(pos, fun, args, dots)
+ switch n.Op() {
+ case ir.OAPPEND:
+ n := n.(*ir.CallExpr)
+ n.RType = reflectdata.TypePtrAt(pos, n.Type().Elem())
+ case ir.OCOPY:
+ n := n.(*ir.BinaryExpr)
+ n.RType = reflectdata.TypePtrAt(pos, n.X.Type().Elem())
+ case ir.ODELETE:
+ n := n.(*ir.CallExpr)
+ n.RType = reflectdata.TypePtrAt(pos, n.Args[0].Type())
+ case ir.OUNSAFESLICE:
+ n := n.(*ir.BinaryExpr)
+ n.RType = reflectdata.TypePtrAt(pos, n.Type().Elem())
+ }
+ return n
case exprMake:
pos := r.pos()
typ := r.exprType(false)
extra := r.exprs()
- return typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...)))
+ n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
+ switch n.Op() {
+ case ir.OMAKECHAN:
+ n.RType = reflectdata.TypePtrAt(pos, typ.Type())
+ case ir.OMAKEMAP:
+ n.RType = reflectdata.TypePtrAt(pos, typ.Type())
+ case ir.OMAKESLICE:
+ n.RType = reflectdata.TypePtrAt(pos, typ.Type().Elem())
+ }
+ return n
case exprNew:
pos := r.pos()
// representing the result slice type's element type.
func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
assertOp(n, ir.OAPPEND)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return sliceElemRType(pos, n.Type())
func CompareRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
assertOp2(n, ir.OEQ, ir.ONE)
base.AssertfAt(n.X.Type().IsInterface() != n.Y.Type().IsInterface(), n.Pos(), "expect mixed interface and non-interface, have %L and %L", n.X, n.Y)
+ // TODO(mdempsky): Need to propagate RType from OSWITCH/OCASE
+ // clauses to emitted OEQ nodes.
if haveRType(n, n.RType, "RType", false) {
return n.RType
}
assertOp(n, ir.OCONVIFACE)
src, dst := n.X.Type(), n.Type()
base.AssertfAt(dst.IsInterface(), n.Pos(), "want interface type, have %L", n)
+ // TODO(mdempsky): Need to handle implicit interface conversions.
if haveRType(n, n.TypeWord, "TypeWord", false) {
return n.TypeWord
}
// the convertee value to the heap.
func ConvIfaceSrcRType(pos src.XPos, n *ir.ConvExpr) ir.Node {
assertOp2(n, ir.OCONVIFACE, ir.OCONVIDATA)
+ // TODO(mdempsky): Need to handle implicit interface conversions.
if haveRType(n, n.SrcRType, "SrcRType", false) {
return n.SrcRType
}
// destination slice type's element type.
func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
assertOp(n, ir.OCOPY)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return sliceElemRType(pos, n.X.Type())
// map type.
func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
assertOp(n, ir.ODELETE)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return mapRType(pos, n.Args[0].Type())
// map type.
func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
assertOp(n, ir.OINDEXMAP)
+ // TODO(mdempsky): Need to propagate RType from OMAPLIT nodes to
+ // emitted OINDEXMAP nodes.
if haveRType(n, n.RType, "RType", false) {
return n.RType
}
// value representing that channel type.
func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
assertOp(n, ir.OMAKECHAN)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return chanRType(pos, n.Type())
// representing that map type.
func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
assertOp(n, ir.OMAKEMAP)
+ // TODO(mdempsky): Need to propagate RType from OMAPLIT nodes to
+ // emitted OMAKEMAP nodes.
if haveRType(n, n.RType, "RType", false) {
return n.RType
}
// value representing that slice type's element type.
func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return sliceElemRType(pos, n.Type())
// representing that map type.
func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
assertOp(n, ir.ORANGE)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return mapRType(pos, n.X.Type())
// representing the result slice type's element type.
func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
assertOp(n, ir.OUNSAFESLICE)
- if haveRType(n, n.RType, "RType", false) {
+ if haveRType(n, n.RType, "RType", true) {
return n.RType
}
return sliceElemRType(pos, n.Type())