aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/reflect
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2023-06-16 12:19:53 -0700
committerRon Evans <[email protected]>2023-07-02 11:47:08 +0200
commitef72c5bb4e544843badec2e2c63ed10a09c281e6 (patch)
treefa4de81ddede753917f48ca83e257b83a17aa88e /src/reflect
parent93cc03b15a6c5e4e9f21d5390084b3012acc54f5 (diff)
downloadtinygo-ef72c5bb4e544843badec2e2c63ed10a09c281e6.tar.gz
tinygo-ef72c5bb4e544843badec2e2c63ed10a09c281e6.zip
reflect: fix iterating over maps with interface{} keys
Fixes #3794
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/value.go21
-rw-r--r--src/reflect/value_test.go18
2 files changed, 30 insertions, 9 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index a5014329c..5ee7e5fc1 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -914,10 +914,11 @@ func (v Value) MapKeys() []Value {
e := New(v.typecode.Elem())
keyType := v.typecode.key()
- isKeyStoredAsInterface := keyType.Kind() != String && !keyType.isBinary()
+ keyTypeIsEmptyInterface := keyType.Kind() == Interface && keyType.NumMethod() == 0
+ shouldUnpackInterface := !keyTypeIsEmptyInterface && keyType.Kind() != String && !keyType.isBinary()
for hashmapNext(v.pointer(), it, k.value, e.value) {
- if isKeyStoredAsInterface {
+ if shouldUnpackInterface {
intf := *(*interface{})(k.value)
v := ValueOf(intf)
keys = append(keys, v)
@@ -992,12 +993,14 @@ func (v Value) MapRange() *MapIter {
}
keyType := v.typecode.key()
- isKeyStoredAsInterface := keyType.Kind() != String && !keyType.isBinary()
+
+ keyTypeIsEmptyInterface := keyType.Kind() == Interface && keyType.NumMethod() == 0
+ shouldUnpackInterface := !keyTypeIsEmptyInterface && keyType.Kind() != String && !keyType.isBinary()
return &MapIter{
- m: v,
- it: hashmapNewIterator(),
- keyInterface: isKeyStoredAsInterface,
+ m: v,
+ it: hashmapNewIterator(),
+ unpackKeyInterface: shouldUnpackInterface,
}
}
@@ -1007,8 +1010,8 @@ type MapIter struct {
key Value
val Value
- valid bool
- keyInterface bool
+ valid bool
+ unpackKeyInterface bool
}
func (it *MapIter) Key() Value {
@@ -1016,7 +1019,7 @@ func (it *MapIter) Key() Value {
panic("reflect.MapIter.Key called on invalid iterator")
}
- if it.keyInterface {
+ if it.unpackKeyInterface {
intf := *(*interface{})(it.key.value)
v := ValueOf(intf)
return v
diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go
index ef6eabcf2..305cf02e8 100644
--- a/src/reflect/value_test.go
+++ b/src/reflect/value_test.go
@@ -191,6 +191,24 @@ func TestTinyMap(t *testing.T) {
if _, ok := utIterKey.Interface().(unmarshalerText); !ok {
t.Errorf("Map keys via MapIter() have wrong type: %v", utIterKey.Type().String())
}
+
+ {
+ m := map[any]any{1: 2}
+ rv := ValueOf(m)
+ iter := rv.MapRange()
+
+ iter.Next()
+ k := iter.Key()
+ if k.Kind().String() != "interface" {
+ t.Errorf("map[any]any MapRange has wrong key type: %v", k.Kind().String())
+ }
+
+ keys := rv.MapKeys()
+ if k := keys[0]; k.Kind().String() != "interface" {
+ t.Errorf("map[any]any MapRange has wrong key type: %v", k.Kind().String())
+ }
+
+ }
}
// For an interface type, it returns the number of exported and unexported methods.