From d667be88310de6f91d9f1a88d949ea6c5b48650d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 30 Jun 2022 14:49:28 -0700 Subject: [PATCH] [dev.unified] cmd/compile/internal/walk: RType fields for range assignments This CL adds extra fields to RangeStmt that can be used when desugaring into primitive assignment statements. This will allow the frontend to wire up all of the RTTI necessary, pulling from dictionaries as necessary. Updates #53328. Change-Id: Iab0e3029ff18c947782ff24f71ef20b2b5cb8305 Reviewed-on: https://go-review.googlesource.com/c/go/+/415518 TryBot-Result: Gopher Robot Reviewed-by: Cuong Manh Le Auto-Submit: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: David Chase --- src/cmd/compile/internal/ir/stmt.go | 8 ++++++++ src/cmd/compile/internal/walk/range.go | 20 ++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 10f8b5e394..cae773b722 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -350,6 +350,14 @@ type RangeStmt struct { Body Nodes HasBreak bool Prealloc *Name + + // When desugaring the RangeStmt during walk, the assignments to Key + // and Value may require OCONVIFACE operations. If so, these fields + // will be copied to their respective ConvExpr fields. + KeyTypeWord Node `mknode:"-"` + KeySrcRType Node `mknode:"-"` + ValueTypeWord Node `mknode:"-"` + ValueSrcRType Node `mknode:"-"` } func NewRangeStmt(pos src.XPos, key, value, x Node, body []Node) *RangeStmt { diff --git a/src/cmd/compile/internal/walk/range.go b/src/cmd/compile/internal/walk/range.go index 60eec25bcf..b697c243c7 100644 --- a/src/cmd/compile/internal/walk/range.go +++ b/src/cmd/compile/internal/walk/range.go @@ -305,7 +305,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { // 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. + key = rangeConvert(n, n.Key.Type(), key, n.KeyTypeWord, n.KeySrcRType) return ir.NewAssignStmt(n.Pos(), n.Key, key) } @@ -313,10 +313,26 @@ func rangeAssign(n *ir.RangeStmt, key ir.Node) ir.Node { 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. + key = rangeConvert(n, n.Key.Type(), key, n.KeyTypeWord, n.KeySrcRType) + value = rangeConvert(n, n.Value.Type(), value, n.ValueTypeWord, n.ValueSrcRType) return ir.NewAssignListStmt(n.Pos(), ir.OAS2, []ir.Node{n.Key, n.Value}, []ir.Node{key, value}) } +// rangeConvert returns src, converted to dst if necessary. If a +// conversion is necessary, then typeWord and srcRType are copied to +// their respective ConvExpr fields. +func rangeConvert(nrange *ir.RangeStmt, dst *types.Type, src, typeWord, srcRType ir.Node) ir.Node { + src = typecheck.Expr(src) + if dst.Kind() == types.TBLANK || types.Identical(dst, src.Type()) { + return src + } + + n := ir.NewConvExpr(nrange.Pos(), ir.OCONV, dst, src) + n.TypeWord = typeWord + n.SrcRType = srcRType + return typecheck.Expr(n) +} + // isMapClear checks if n is of the form: // // for k := range m { -- 2.50.0