Skip to content

Commit 8dab959

Browse files
committed
reflect: rename Mapiter.SetKey to Value.SetIterKey
Same for Value. Add a bigger test. Include some shouldPanic checks. Fix a bug in assignment conversion. Fixes #48294 Change-Id: Id863ee5122a5787a7b35574b18586fd24d118788 Reviewed-on: https://go-review.googlesource.com/c/go/+/356049 Trust: Keith Randall <[email protected]> Trust: Josh Bleecher Snyder <[email protected]> Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Josh Bleecher Snyder <[email protected]>
1 parent 3da0ff8 commit 8dab959

File tree

2 files changed

+108
-30
lines changed

2 files changed

+108
-30
lines changed

src/reflect/all_test.go

+84-6
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,8 @@ func TestMapIterSet(t *testing.T) {
348348

349349
iter := v.MapRange()
350350
for iter.Next() {
351-
iter.SetKey(k)
352-
iter.SetValue(e)
351+
k.SetIterKey(iter)
352+
e.SetIterValue(iter)
353353
want := m[k.String()]
354354
got := e.Interface()
355355
if got != want {
@@ -366,8 +366,8 @@ func TestMapIterSet(t *testing.T) {
366366
got := int(testing.AllocsPerRun(10, func() {
367367
iter := v.MapRange()
368368
for iter.Next() {
369-
iter.SetKey(k)
370-
iter.SetValue(e)
369+
k.SetIterKey(iter)
370+
e.SetIterValue(iter)
371371
}
372372
}))
373373
// Making a *MapIter allocates. This should be the only allocation.
@@ -7475,9 +7475,9 @@ func TestMapIterReset(t *testing.T) {
74757475
var seenk, seenv uint64
74767476
iter.Reset(ValueOf(m3))
74777477
for iter.Next() {
7478-
iter.SetKey(kv)
7478+
kv.SetIterKey(iter)
74797479
seenk ^= kv.Uint()
7480-
iter.SetValue(kv)
7480+
kv.SetIterValue(iter)
74817481
seenv ^= kv.Uint()
74827482
}
74837483
if seenk != 0b111 {
@@ -7619,3 +7619,81 @@ func TestConvertibleTo(t *testing.T) {
76197619
t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t3, t4)
76207620
}
76217621
}
7622+
7623+
func TestSetIter(t *testing.T) {
7624+
data := map[string]int{
7625+
"foo": 1,
7626+
"bar": 2,
7627+
"baz": 3,
7628+
}
7629+
7630+
m := ValueOf(data)
7631+
i := m.MapRange()
7632+
k := New(TypeOf("")).Elem()
7633+
v := New(TypeOf(0)).Elem()
7634+
shouldPanic("Value.SetIterKey called before Next", func() {
7635+
k.SetIterKey(i)
7636+
})
7637+
shouldPanic("Value.SetIterValue called before Next", func() {
7638+
k.SetIterValue(i)
7639+
})
7640+
data2 := map[string]int{}
7641+
for i.Next() {
7642+
k.SetIterKey(i)
7643+
v.SetIterValue(i)
7644+
data2[k.Interface().(string)] = v.Interface().(int)
7645+
}
7646+
if !DeepEqual(data, data2) {
7647+
t.Errorf("maps not equal, got %v want %v", data2, data)
7648+
}
7649+
shouldPanic("Value.SetIterKey called on exhausted iterator", func() {
7650+
k.SetIterKey(i)
7651+
})
7652+
shouldPanic("Value.SetIterValue called on exhausted iterator", func() {
7653+
k.SetIterValue(i)
7654+
})
7655+
7656+
i.Reset(m)
7657+
i.Next()
7658+
shouldPanic("Value.SetIterKey using unaddressable value", func() {
7659+
ValueOf("").SetIterKey(i)
7660+
})
7661+
shouldPanic("Value.SetIterValue using unaddressable value", func() {
7662+
ValueOf(0).SetIterValue(i)
7663+
})
7664+
shouldPanic("value of type string is not assignable to type int", func() {
7665+
New(TypeOf(0)).Elem().SetIterKey(i)
7666+
})
7667+
shouldPanic("value of type int is not assignable to type string", func() {
7668+
New(TypeOf("")).Elem().SetIterValue(i)
7669+
})
7670+
7671+
// Make sure assignment conversion works.
7672+
var x interface{}
7673+
y := ValueOf(&x).Elem()
7674+
y.SetIterKey(i)
7675+
if _, ok := data[x.(string)]; !ok {
7676+
t.Errorf("got key %s which is not in map", x)
7677+
}
7678+
y.SetIterValue(i)
7679+
if x.(int) < 1 || x.(int) > 3 {
7680+
t.Errorf("got value %d which is not in map", x)
7681+
}
7682+
7683+
// Try some key/value types which are direct interfaces.
7684+
a := 88
7685+
b := 99
7686+
pp := map[*int]*int{
7687+
&a: &b,
7688+
}
7689+
i = ValueOf(pp).MapRange()
7690+
i.Next()
7691+
y.SetIterKey(i)
7692+
if got := *y.Interface().(*int); got != a {
7693+
t.Errorf("pointer incorrect: got %d want %d", got, a)
7694+
}
7695+
y.SetIterValue(i)
7696+
if got := *y.Interface().(*int); got != b {
7697+
t.Errorf("pointer incorrect: got %d want %d", got, b)
7698+
}
7699+
}

src/reflect/value.go

+24-24
Original file line numberDiff line numberDiff line change
@@ -1651,30 +1651,30 @@ func (iter *MapIter) Key() Value {
16511651
return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey)
16521652
}
16531653

1654-
// SetKey assigns dst to the key of iter's current map entry.
1655-
// It is equivalent to dst.Set(i.Key()), but it avoids allocating a new Value.
1656-
// As in Go, the key must be assignable to dst's type.
1657-
func (iter *MapIter) SetKey(dst Value) {
1654+
// SetIterKey assigns to v the key of iter's current map entry.
1655+
// It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value.
1656+
// As in Go, the key must be assignable to v's type.
1657+
func (v Value) SetIterKey(iter *MapIter) {
16581658
if !iter.hiter.initialized() {
1659-
panic("MapIter.SetKey called before Next")
1659+
panic("reflect: Value.SetIterKey called before Next")
16601660
}
16611661
iterkey := mapiterkey(&iter.hiter)
16621662
if iterkey == nil {
1663-
panic("MapIter.SetKey called on exhausted iterator")
1663+
panic("reflect: Value.SetIterKey called on exhausted iterator")
16641664
}
16651665

1666-
dst.mustBeAssignable()
1666+
v.mustBeAssignable()
16671667
var target unsafe.Pointer
1668-
if dst.kind() == Interface {
1669-
target = dst.ptr
1668+
if v.kind() == Interface {
1669+
target = v.ptr
16701670
}
16711671

16721672
t := (*mapType)(unsafe.Pointer(iter.m.typ))
16731673
ktype := t.key
16741674

1675-
key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind())}
1676-
key = key.assignTo("reflect.MapIter.SetKey", dst.typ, target)
1677-
typedmemmove(dst.typ, dst.ptr, key.ptr)
1675+
key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind()) | flagIndir}
1676+
key = key.assignTo("reflect.MapIter.SetKey", v.typ, target)
1677+
typedmemmove(v.typ, v.ptr, key.ptr)
16781678
}
16791679

16801680
// Value returns the value of iter's current map entry.
@@ -1692,30 +1692,30 @@ func (iter *MapIter) Value() Value {
16921692
return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem)
16931693
}
16941694

1695-
// SetValue assigns dst to the value of iter's current map entry.
1696-
// It is equivalent to dst.Set(i.Value()), but it avoids allocating a new Value.
1697-
// As in Go, the value must be assignable to dst's type.
1698-
func (iter *MapIter) SetValue(dst Value) {
1695+
// SetIterValue assigns to v the value of iter's current map entry.
1696+
// It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value.
1697+
// As in Go, the value must be assignable to v's type.
1698+
func (v Value) SetIterValue(iter *MapIter) {
16991699
if !iter.hiter.initialized() {
1700-
panic("MapIter.SetValue called before Next")
1700+
panic("reflect: Value.SetIterValue called before Next")
17011701
}
17021702
iterelem := mapiterelem(&iter.hiter)
17031703
if iterelem == nil {
1704-
panic("MapIter.SetValue called on exhausted iterator")
1704+
panic("reflect: Value.SetIterValue called on exhausted iterator")
17051705
}
17061706

1707-
dst.mustBeAssignable()
1707+
v.mustBeAssignable()
17081708
var target unsafe.Pointer
1709-
if dst.kind() == Interface {
1710-
target = dst.ptr
1709+
if v.kind() == Interface {
1710+
target = v.ptr
17111711
}
17121712

17131713
t := (*mapType)(unsafe.Pointer(iter.m.typ))
17141714
vtype := t.elem
17151715

1716-
elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind())}
1717-
elem = elem.assignTo("reflect.MapIter.SetValue", dst.typ, target)
1718-
typedmemmove(dst.typ, dst.ptr, elem.ptr)
1716+
elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind()) | flagIndir}
1717+
elem = elem.assignTo("reflect.MapIter.SetValue", v.typ, target)
1718+
typedmemmove(v.typ, v.ptr, elem.ptr)
17191719
}
17201720

17211721
// Next advances the map iterator and reports whether there is another

0 commit comments

Comments
 (0)