diff options
author | Damian Gryski <[email protected]> | 2023-12-12 21:51:26 -0800 |
---|---|---|
committer | Ron Evans <[email protected]> | 2024-01-31 13:48:02 +0100 |
commit | 5b8127fd4ea3bd3134f93e07250d595dfbde14ba (patch) | |
tree | 0363bafeedb0564284a323a8e9dbbfff0c6b7f17 /src/reflect | |
parent | cc3e7856928492b16c20e31f5a7bf331e324b1e8 (diff) | |
download | tinygo-5b8127fd4ea3bd3134f93e07250d595dfbde14ba.tar.gz tinygo-5b8127fd4ea3bd3134f93e07250d595dfbde14ba.zip |
reflect: move indirect values into interface when setting interfaces
Fixes #4040
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/value.go | 7 | ||||
-rw-r--r-- | src/reflect/value_test.go | 22 |
2 files changed, 29 insertions, 0 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go index 1227ac422..16d2a17b5 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1086,6 +1086,13 @@ func (v Value) Set(x Value) { } if v.typecode.Kind() == Interface && x.typecode.Kind() != Interface { + // move the value of x back into the interface, if possible + if x.isIndirect() && x.typecode.Size() <= unsafe.Sizeof(uintptr(0)) { + var value uintptr + memcpy(unsafe.Pointer(&value), x.value, x.typecode.Size()) + x.value = unsafe.Pointer(value) + } + intf := composeInterface(unsafe.Pointer(x.typecode), x.value) x = Value{ typecode: v.typecode, diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index 9be9789e1..6641750b9 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -624,6 +624,28 @@ func TestConvert(t *testing.T) { } } +func TestIssue4040(t *testing.T) { + var value interface{} = uint16(0) + + // get the pointer to the interface value + inPtr := ValueOf(&value) + + // dereference to get the actual value (an interface) + inElem := inPtr.Elem() + + // create a new value of the same concrete type + uint16Type := TypeOf(uint16(0)) + newUint16Value := New(uint16Type).Elem() + newUint16Value.Set(ValueOf(uint16(13))) + + // set the new value to the interface + inElem.Set(newUint16Value) + + if value.(uint16) != 13 { + t.Errorf("Failed to set interface value from uint16") + } +} + func equal[T comparable](a, b []T) bool { if len(a) != len(b) { return false |