Closed hunjixin closed 1 year ago
Reflection isn't very well supported in tinygo at the moment - there are some parts that are being worked on, but I don't know if I'd ever count of complete support for reflection.
The code you wrote, doesn't look like it need reflection in particular however - as it appears to just be constructing a *bool
here is the cast : I converted the go code to wasm to run, but there is a dependency package that has this code
https://github.com/polydawn/refmt/blob/30ac6d18308e584ca6a2e74ba81475559db94c5f/obj/builtins.go#L8
the author uses this type address as the map key,this maybe slightly faster than the reflect type as the key
Here is the relevant piece of code, just FYI:
https://github.com/tinygo-org/tinygo/blob/release/src/reflect/value.go#L135-L149
https://github.com/tinygo-org/tinygo/blob/release/src/reflect/value.go#L135-L149
yeap, i have dig here, its Uintptr type, maybe can convert this value to unsafe.Pointer and return. its okay?
The dependency you mentioned uses reflect heavily, so might be hard to get running in tinygo... though I haven't checked. https://github.com/polydawn/refmt
@dankegel In fact, it may not be used, but it's in the init, and it fails in the initAll func when just start program....
So, I tried running polydown/refmt's tests in tinygo, but they failed as follows:
refmt dkegel$ GO111MODULE=off GOPATH="$PWD/.gopath/" tinygo test ./... -v
# github.com/smartystreets/assertions/internal/go-render/render
.gopath/src/github.com/smartystreets/assertions/internal/go-render/render/render.go:318:19: MapOf not declared by package reflect
.gopath/src/github.com/smartystreets/assertions/internal/go-render/render/render.go:418:15: av.InterfaceData undefined (type reflect.Value has no field or method InterfaceData)
.gopath/src/github.com/smartystreets/assertions/internal/go-render/render/render.go:418:35: bv.InterfaceData undefined (type reflect.Value has no field or method InterfaceData)
FAIL
very said, this is the dependency of the project's dependency, and most of the functions are not used. I just want to make it as easy as possible to get past this init issue, there are too many to rewrites. I'm also not sure if other dependencies have the same issue.
as metion before could i add code in Pointer to resolve Uintptr type like this, i am sure its okay or not
// Pointer returns the underlying pointer of the given value for the following
// types: chan, map, pointer, unsafe.Pointer, slice, func.
func (v Value) Pointer() uintptr {
switch v.Kind() {
case Chan, Map, Ptr, UnsafePointer:
return uintptr(v.pointer())
case Slice:
slice := (*sliceHeader)(v.value)
return uintptr(slice.data)
case Uintptr:
return uintptr(v.value)
case Func:
panic("unimplemented: (reflect.Value).Pointer()")
default: // not implemented: Func
panic(&ValueError{Method: "Pointer"})
}
}
Ack there are many issues open about reflection, but I figured I would get specific on this one, as we didn't have the full source. @hunjixin is this what you were trying, and also on https://github.com/tinygo-org/tinygo/issues/2858#issuecomment-1133519485 can you be specific to which file you are patching?
package main
import "reflect"
var pointer = reflect.ValueOf(reflect.TypeOf(false)).Pointer()
func main() {
}
normal
panic: reflect: call of UnsafePointer on zero Value
Abort trap: 6
wasi
panic: reflect: call of UnsafePointer on zero Value
Error: failed to run main module `main.wasm`
Caused by:
0: failed to invoke command default
1: wasm trap: wasm `unreachable` instruction executed
wasm backtrace:
0: 0x93f - <unknown>!runtime._panic
1: 0x45c - <unknown>!(reflect.Value).Pointer
2: 0x25cd - <unknown>!runtime.initAll
3: 0x255a - <unknown>!runtime.run$1
4: 0x2498 - <unknown>!runtime.run$1$gowrapper
5: 0x2616 - <unknown>!tinygo_launch
6: 0x235c - <unknown>!_start
@hunjixin the code change you have suggested is not correct, because it does not match the API of the reflect package:
Pointer returns v's value as a uintptr. It returns uintptr instead of unsafe.Pointer so that code using reflect cannot obtain unsafe.Pointers without importing the unsafe package explicitly. It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer.
A uintptr
is not a pointer. Therefore, Pointer()
shouldn't return it as a pointer.
But it looks like there is a bug here because reflect.ValueOf(reflect.TypeOf(false)).Pointer()
does not panic in Go.
On second thought, it looks like the code is doing something non-portable:
var (
rtid_bool = ValueOf(TypeOf(false)).Pointer()
rtid_string = ValueOf(TypeOf("")).Pointer()
rtid_bytes = ValueOf(TypeOf([]byte{})).Pointer()
rtid_int = ValueOf(TypeOf(int(0))).Pointer()
rtid_int8 = ValueOf(TypeOf(int8(0))).Pointer()
rtid_int16 = ValueOf(TypeOf(int16(0))).Pointer()
rtid_int32 = ValueOf(TypeOf(int32(0))).Pointer()
rtid_int64 = ValueOf(TypeOf(int64(0))).Pointer()
rtid_uint = ValueOf(TypeOf(uint(0))).Pointer()
rtid_uint8 = ValueOf(TypeOf(uint8(0))).Pointer()
rtid_uint16 = ValueOf(TypeOf(uint16(0))).Pointer()
rtid_uint32 = ValueOf(TypeOf(uint32(0))).Pointer()
rtid_uint64 = ValueOf(TypeOf(uint64(0))).Pointer()
rtid_uintptr = ValueOf(TypeOf(uintptr(0))).Pointer()
rtid_float32 = ValueOf(TypeOf(float32(0))).Pointer()
rtid_float64 = ValueOf(TypeOf(float64(0))).Pointer()
)
It looks like they are inspecting the underlying type of reflect.Type
. Don't do that. It's an implementation detail.
I don't think there is much that TinyGo can do (although #2640 might fix this as an unintended side effect).
These are now unique, but please don't do this.
~/go/src/github.com/dgryski/bug/m $ cat main.go
package main
import (
. "reflect"
)
func main() {
var (
rtid_bool = ValueOf(TypeOf(false)).Pointer()
rtid_string = ValueOf(TypeOf("")).Pointer()
rtid_bytes = ValueOf(TypeOf([]byte{})).Pointer()
rtid_int = ValueOf(TypeOf(int(0))).Pointer()
rtid_int8 = ValueOf(TypeOf(int8(0))).Pointer()
rtid_int16 = ValueOf(TypeOf(int16(0))).Pointer()
rtid_int32 = ValueOf(TypeOf(int32(0))).Pointer()
rtid_int64 = ValueOf(TypeOf(int64(0))).Pointer()
rtid_uint = ValueOf(TypeOf(uint(0))).Pointer()
rtid_uint8 = ValueOf(TypeOf(uint8(0))).Pointer()
rtid_uint16 = ValueOf(TypeOf(uint16(0))).Pointer()
rtid_uint32 = ValueOf(TypeOf(uint32(0))).Pointer()
rtid_uint64 = ValueOf(TypeOf(uint64(0))).Pointer()
rtid_uintptr = ValueOf(TypeOf(uintptr(0))).Pointer()
rtid_float32 = ValueOf(TypeOf(float32(0))).Pointer()
rtid_float64 = ValueOf(TypeOf(float64(0))).Pointer()
)
println(rtid_bool)
println(rtid_string)
println(rtid_bytes)
println(rtid_int)
println(rtid_int8)
println(rtid_int16)
println(rtid_int32)
println(rtid_int64)
println(rtid_uint)
println(rtid_uint8)
println(rtid_uint16)
println(rtid_uint32)
println(rtid_uint64)
println(rtid_uintptr)
println(rtid_float32)
println(rtid_float64)
}
~/go/src/github.com/dgryski/bug/m $ tinygo run main.go |sort |uniq -c |sort -n
1 0x00000001065f0030
1 0x00000001065f0070
1 0x00000001065f00b0
1 0x00000001065f00f8
1 0x00000001065f0138
1 0x00000001065f0178
1 0x00000001065f01b8
1 0x00000001065f01f8
1 0x00000001065f0238
1 0x00000001065f0278
1 0x00000001065f02b8
1 0x00000001065f02f8
1 0x00000001065f0338
1 0x00000001065f0378
1 0x00000001065f03b8
1 0x00000001065f03f8
good work. I don't want to do this, but it's from someone else's library. i have to fork and replace it before.
This is part of the v0.28
release so now closing this issue. Thanks!
this code is golang, and in tinygo got panic, how to write it in tinygo?