Skip to content

Commit

Permalink
fix(gnovm): allow private struct fields to be set
Browse files Browse the repository at this point in the history
Go reflect doesn't allow to set unexported struct fields.
We use `unsafe` to override this limitation.

Fixes #1155 and #3812
  • Loading branch information
mvertes committed Feb 24, 2025
1 parent 85b3c0b commit 5d3f635
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
8 changes: 7 additions & 1 deletion gnovm/pkg/gnolang/gonative.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"math"
"reflect"
"unsafe"

"github.com/gnolang/gno/gnovm/pkg/gnolang/internal/softfloat"
)
Expand Down Expand Up @@ -1133,7 +1134,12 @@ func gno2GoValue(tv *TypedValue, rv reflect.Value) (ret reflect.Value) {
if ftv.IsUndefined() {
continue
}
gno2GoValue(ftv, rv.Field(i))
fv := rv.Field(i)
if !fv.CanSet() {
// Normally private fields can not bet set via reflect. Override this limitation.
fv = reflect.NewAt(fv.Type(), unsafe.Pointer(fv.UnsafeAddr())).Elem()
}
gno2GoValue(ftv, fv)
}
case *MapType:
// If uninitialized map, return zero value.
Expand Down
15 changes: 15 additions & 0 deletions gnovm/tests/files/struct59.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import "fmt"

type X struct {
v string
}

func main() {
x := X{v: "a"}
fmt.Printf("test %#v\n", x)
}

// Output:
// test struct { v string }{v:"a"}

0 comments on commit 5d3f635

Please sign in to comment.