diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 5ebc776605..7588e52d96 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1390,6 +1390,9 @@ func (r *reader) forStmt(label *types.Sym) ir.Node { 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 { @@ -1632,7 +1635,13 @@ func (r *reader) expr() (res ir.Node) { 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() @@ -1654,6 +1663,7 @@ func (r *reader) expr() (res ir.Node) { 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) } @@ -1682,7 +1692,19 @@ func (r *reader) expr() (res ir.Node) { 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() @@ -1694,13 +1716,37 @@ func (r *reader) expr() (res ir.Node) { 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() diff --git a/src/cmd/compile/internal/reflectdata/helpers.go b/src/cmd/compile/internal/reflectdata/helpers.go index 4d85dea74d..22431a2bcb 100644 --- a/src/cmd/compile/internal/reflectdata/helpers.go +++ b/src/cmd/compile/internal/reflectdata/helpers.go @@ -71,7 +71,7 @@ func concreteRType(pos src.XPos, typ *types.Type) ir.Node { // 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()) @@ -84,6 +84,8 @@ func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node { 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 } @@ -105,6 +107,7 @@ func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node { 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 } @@ -123,6 +126,7 @@ func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node { // 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 } @@ -134,7 +138,7 @@ func ConvIfaceSrcRType(pos src.XPos, n *ir.ConvExpr) ir.Node { // 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()) @@ -145,7 +149,7 @@ func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node { // 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()) @@ -156,6 +160,8 @@ func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node { // 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 } @@ -167,7 +173,7 @@ func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node { // 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()) @@ -178,6 +184,8 @@ func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node { // 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 } @@ -189,7 +197,7 @@ func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node { // 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()) @@ -200,7 +208,7 @@ func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node { // 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()) @@ -211,7 +219,7 @@ func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node { // 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())