]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: rename Mapiter.SetKey to Value.SetIterKey
authorKeith Randall <khr@golang.org>
Fri, 15 Oct 2021 00:30:42 +0000 (17:30 -0700)
committerKeith Randall <khr@golang.org>
Fri, 15 Oct 2021 03:49:17 +0000 (03:49 +0000)
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 <khr@golang.org>
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/reflect/all_test.go
src/reflect/value.go

index 5e10cc7a633dbd2ff12c9df12c7a8f42a822f494..58156e0e5f1641dc94eef56eda1f403268811ed1 100644 (file)
@@ -348,8 +348,8 @@ func TestMapIterSet(t *testing.T) {
 
        iter := v.MapRange()
        for iter.Next() {
-               iter.SetKey(k)
-               iter.SetValue(e)
+               k.SetIterKey(iter)
+               e.SetIterValue(iter)
                want := m[k.String()]
                got := e.Interface()
                if got != want {
@@ -366,8 +366,8 @@ func TestMapIterSet(t *testing.T) {
        got := int(testing.AllocsPerRun(10, func() {
                iter := v.MapRange()
                for iter.Next() {
-                       iter.SetKey(k)
-                       iter.SetValue(e)
+                       k.SetIterKey(iter)
+                       e.SetIterValue(iter)
                }
        }))
        // Making a *MapIter allocates. This should be the only allocation.
@@ -7475,9 +7475,9 @@ func TestMapIterReset(t *testing.T) {
                var seenk, seenv uint64
                iter.Reset(ValueOf(m3))
                for iter.Next() {
-                       iter.SetKey(kv)
+                       kv.SetIterKey(iter)
                        seenk ^= kv.Uint()
-                       iter.SetValue(kv)
+                       kv.SetIterValue(iter)
                        seenv ^= kv.Uint()
                }
                if seenk != 0b111 {
@@ -7619,3 +7619,81 @@ func TestConvertibleTo(t *testing.T) {
                t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t3, t4)
        }
 }
+
+func TestSetIter(t *testing.T) {
+       data := map[string]int{
+               "foo": 1,
+               "bar": 2,
+               "baz": 3,
+       }
+
+       m := ValueOf(data)
+       i := m.MapRange()
+       k := New(TypeOf("")).Elem()
+       v := New(TypeOf(0)).Elem()
+       shouldPanic("Value.SetIterKey called before Next", func() {
+               k.SetIterKey(i)
+       })
+       shouldPanic("Value.SetIterValue called before Next", func() {
+               k.SetIterValue(i)
+       })
+       data2 := map[string]int{}
+       for i.Next() {
+               k.SetIterKey(i)
+               v.SetIterValue(i)
+               data2[k.Interface().(string)] = v.Interface().(int)
+       }
+       if !DeepEqual(data, data2) {
+               t.Errorf("maps not equal, got %v want %v", data2, data)
+       }
+       shouldPanic("Value.SetIterKey called on exhausted iterator", func() {
+               k.SetIterKey(i)
+       })
+       shouldPanic("Value.SetIterValue called on exhausted iterator", func() {
+               k.SetIterValue(i)
+       })
+
+       i.Reset(m)
+       i.Next()
+       shouldPanic("Value.SetIterKey using unaddressable value", func() {
+               ValueOf("").SetIterKey(i)
+       })
+       shouldPanic("Value.SetIterValue using unaddressable value", func() {
+               ValueOf(0).SetIterValue(i)
+       })
+       shouldPanic("value of type string is not assignable to type int", func() {
+               New(TypeOf(0)).Elem().SetIterKey(i)
+       })
+       shouldPanic("value of type int is not assignable to type string", func() {
+               New(TypeOf("")).Elem().SetIterValue(i)
+       })
+
+       // Make sure assignment conversion works.
+       var x interface{}
+       y := ValueOf(&x).Elem()
+       y.SetIterKey(i)
+       if _, ok := data[x.(string)]; !ok {
+               t.Errorf("got key %s which is not in map", x)
+       }
+       y.SetIterValue(i)
+       if x.(int) < 1 || x.(int) > 3 {
+               t.Errorf("got value %d which is not in map", x)
+       }
+
+       // Try some key/value types which are direct interfaces.
+       a := 88
+       b := 99
+       pp := map[*int]*int{
+               &a: &b,
+       }
+       i = ValueOf(pp).MapRange()
+       i.Next()
+       y.SetIterKey(i)
+       if got := *y.Interface().(*int); got != a {
+               t.Errorf("pointer incorrect: got %d want %d", got, a)
+       }
+       y.SetIterValue(i)
+       if got := *y.Interface().(*int); got != b {
+               t.Errorf("pointer incorrect: got %d want %d", got, b)
+       }
+}
index 39b82a8c01fbe5634483a69a3af6001a493504b3..abcc346de8a4947d8eba066d1e1f09720a641226 100644 (file)
@@ -1651,30 +1651,30 @@ func (iter *MapIter) Key() Value {
        return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey)
 }
 
-// SetKey assigns dst to the key of iter's current map entry.
-// It is equivalent to dst.Set(i.Key()), but it avoids allocating a new Value.
-// As in Go, the key must be assignable to dst's type.
-func (iter *MapIter) SetKey(dst Value) {
+// SetIterKey assigns to v the key of iter's current map entry.
+// It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value.
+// As in Go, the key must be assignable to v's type.
+func (v Value) SetIterKey(iter *MapIter) {
        if !iter.hiter.initialized() {
-               panic("MapIter.SetKey called before Next")
+               panic("reflect: Value.SetIterKey called before Next")
        }
        iterkey := mapiterkey(&iter.hiter)
        if iterkey == nil {
-               panic("MapIter.SetKey called on exhausted iterator")
+               panic("reflect: Value.SetIterKey called on exhausted iterator")
        }
 
-       dst.mustBeAssignable()
+       v.mustBeAssignable()
        var target unsafe.Pointer
-       if dst.kind() == Interface {
-               target = dst.ptr
+       if v.kind() == Interface {
+               target = v.ptr
        }
 
        t := (*mapType)(unsafe.Pointer(iter.m.typ))
        ktype := t.key
 
-       key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind())}
-       key = key.assignTo("reflect.MapIter.SetKey", dst.typ, target)
-       typedmemmove(dst.typ, dst.ptr, key.ptr)
+       key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind()) | flagIndir}
+       key = key.assignTo("reflect.MapIter.SetKey", v.typ, target)
+       typedmemmove(v.typ, v.ptr, key.ptr)
 }
 
 // Value returns the value of iter's current map entry.
@@ -1692,30 +1692,30 @@ func (iter *MapIter) Value() Value {
        return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem)
 }
 
-// SetValue assigns dst to the value of iter's current map entry.
-// It is equivalent to dst.Set(i.Value()), but it avoids allocating a new Value.
-// As in Go, the value must be assignable to dst's type.
-func (iter *MapIter) SetValue(dst Value) {
+// SetIterValue assigns to v the value of iter's current map entry.
+// It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value.
+// As in Go, the value must be assignable to v's type.
+func (v Value) SetIterValue(iter *MapIter) {
        if !iter.hiter.initialized() {
-               panic("MapIter.SetValue called before Next")
+               panic("reflect: Value.SetIterValue called before Next")
        }
        iterelem := mapiterelem(&iter.hiter)
        if iterelem == nil {
-               panic("MapIter.SetValue called on exhausted iterator")
+               panic("reflect: Value.SetIterValue called on exhausted iterator")
        }
 
-       dst.mustBeAssignable()
+       v.mustBeAssignable()
        var target unsafe.Pointer
-       if dst.kind() == Interface {
-               target = dst.ptr
+       if v.kind() == Interface {
+               target = v.ptr
        }
 
        t := (*mapType)(unsafe.Pointer(iter.m.typ))
        vtype := t.elem
 
-       elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind())}
-       elem = elem.assignTo("reflect.MapIter.SetValue", dst.typ, target)
-       typedmemmove(dst.typ, dst.ptr, elem.ptr)
+       elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind()) | flagIndir}
+       elem = elem.assignTo("reflect.MapIter.SetValue", v.typ, target)
+       typedmemmove(v.typ, v.ptr, elem.ptr)
 }
 
 // Next advances the map iterator and reports whether there is another