From 0a503cf43a58e3a514f254c7dba1daf654557b17 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 29 Jun 2022 19:23:34 -0700 Subject: [PATCH] [dev.unified] cmd/compile: refactor `range` desugaring This CL refactors the code responsible for emitting the user-visible assignments within a range statement. This will make it easier to propagate RTTI from the frontend into any implicit conversions. Updates #53328. Change-Id: Ibed15e3b4951b0a6a726067b401a630977f4c6c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/415158 Reviewed-by: David Chase Reviewed-by: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Gopher Robot --- src/cmd/compile/internal/walk/range.go | 37 +++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/walk/range.go b/src/cmd/compile/internal/walk/range.go index 16d7595baa..60eec25bcf 100644 --- a/src/cmd/compile/internal/walk/range.go +++ b/src/cmd/compile/internal/walk/range.go @@ -103,7 +103,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { // for v1 := range ha { body } if v2 == nil { - body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, hv1)} + body = []ir.Node{rangeAssign(nrange, hv1)} break } @@ -112,10 +112,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { // v1, v2 = hv1, ha[hv1] tmp := ir.NewIndexExpr(base.Pos, ha, hv1) tmp.SetBounded(true) - // Use OAS2 to correctly handle assignments - // of the form "v1, a[v1] := range". - a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{hv1, tmp}) - body = []ir.Node{a} + body = []ir.Node{rangeAssign2(nrange, hv1, tmp)} break } @@ -140,9 +137,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { tmp.SetBounded(true) init = append(init, ir.NewAssignStmt(base.Pos, hp, typecheck.NodAddr(tmp))) - // Use OAS2 to correctly handle assignments - // of the form "v1, a[v1] := range". - a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{hv1, ir.NewStarExpr(base.Pos, hp)}) + a := rangeAssign2(nrange, hv1, ir.NewStarExpr(base.Pos, hp)) body = append(body, a) // Advance pointer as part of the late increment. @@ -179,11 +174,10 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { if v1 == nil { body = nil } else if v2 == nil { - body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, key)} + body = []ir.Node{rangeAssign(nrange, key)} } else { elem := ir.NewStarExpr(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, elemsym)) - a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{key, elem}) - body = []ir.Node{a} + body = []ir.Node{rangeAssign2(nrange, key, elem)} } case types.TCHAN: @@ -206,7 +200,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { if v1 == nil { body = nil } else { - body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, hv1)} + body = []ir.Node{rangeAssign(nrange, hv1)} } // Zero hv1. This prevents hv1 from being the sole, inaccessible // reference to an otherwise GC-able value during the next channel receive. @@ -271,11 +265,10 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { if v1 != nil { if v2 != nil { // v1, v2 = hv1t, hv2 - a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{hv1t, hv2}) - body = append(body, a) + body = append(body, rangeAssign2(nrange, hv1t, hv2)) } else { // v1 = hv1t - body = append(body, ir.NewAssignStmt(base.Pos, v1, hv1t)) + body = append(body, rangeAssign(nrange, hv1t)) } } } @@ -310,6 +303,20 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { return n } +// rangeAssign returns "n.Key = key". +func rangeAssign(n *ir.RangeStmt, key ir.Node) ir.Node { + // TODO(mdempsky): Implicit conversions for test/typeparam/mdempsky/17.go. + return ir.NewAssignStmt(n.Pos(), n.Key, key) +} + +// rangeAssign2 returns "n.Key, n.Value = key, value". +func rangeAssign2(n *ir.RangeStmt, key, value ir.Node) ir.Node { + // Use OAS2 to correctly handle assignments + // of the form "v1, a[v1] = range". + // TODO(mdempsky): Implicit conversions for test/typeparam/mdempsky/17.go. + return ir.NewAssignListStmt(n.Pos(), ir.OAS2, []ir.Node{n.Key, n.Value}, []ir.Node{key, value}) +} + // isMapClear checks if n is of the form: // // for k := range m { -- 2.50.0