aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/reflect
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2023-12-12 21:51:26 -0800
committerRon Evans <[email protected]>2024-01-31 13:48:02 +0100
commit5b8127fd4ea3bd3134f93e07250d595dfbde14ba (patch)
tree0363bafeedb0564284a323a8e9dbbfff0c6b7f17 /src/reflect
parentcc3e7856928492b16c20e31f5a7bf331e324b1e8 (diff)
downloadtinygo-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.go7
-rw-r--r--src/reflect/value_test.go22
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