mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-05 19:43:44 +00:00
reflect: let reflect.Type be of interface type
This matches the main Go implementation and (among others) fixes a compatibility issue with the encoding/json package. The encoding/json package compares reflect.Type variables against nil, which does not work as long as reflect.Type is of integer type. This also adds a reflect.RawType() function (like reflect.Type()) that makes it easier to avoid working with interfaces in the runtime package. It is internal only, but exported to let the runtime package use it. This change introduces a small code size increase when working with the reflect package, but I've tried to keep it to a minimum. Most programs that don't make extensive use of the reflect package (and don't use package like fmt) should not be impacted by this.
This commit is contained in:
committed by
Ron Evans
parent
cffe424849
commit
c849bccb83
@@ -351,36 +351,36 @@ func hashmapStringDelete(m *hashmap, key string) {
|
||||
|
||||
func hashmapInterfaceHash(itf interface{}) uint32 {
|
||||
x := reflect.ValueOf(itf)
|
||||
if x.Type() == 0 {
|
||||
if x.RawType() == 0 {
|
||||
return 0 // nil interface
|
||||
}
|
||||
|
||||
value := (*_interface)(unsafe.Pointer(&itf)).value
|
||||
ptr := value
|
||||
if x.Type().Size() <= unsafe.Sizeof(uintptr(0)) {
|
||||
if x.RawType().Size() <= unsafe.Sizeof(uintptr(0)) {
|
||||
// Value fits in pointer, so it's directly stored in the pointer.
|
||||
ptr = unsafe.Pointer(&value)
|
||||
}
|
||||
|
||||
switch x.Type().Kind() {
|
||||
switch x.RawType().Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return hashmapHash(ptr, x.Type().Size())
|
||||
return hashmapHash(ptr, x.RawType().Size())
|
||||
case reflect.Bool, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return hashmapHash(ptr, x.Type().Size())
|
||||
return hashmapHash(ptr, x.RawType().Size())
|
||||
case reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
|
||||
// It should be possible to just has the contents. However, NaN != NaN
|
||||
// so if you're using lots of NaNs as map keys (you shouldn't) then hash
|
||||
// time may become exponential. To fix that, it would be better to
|
||||
// return a random number instead:
|
||||
// https://research.swtch.com/randhash
|
||||
return hashmapHash(ptr, x.Type().Size())
|
||||
return hashmapHash(ptr, x.RawType().Size())
|
||||
case reflect.String:
|
||||
return hashmapStringHash(x.String())
|
||||
case reflect.Chan, reflect.Ptr, reflect.UnsafePointer:
|
||||
// It might seem better to just return the pointer, but that won't
|
||||
// result in an evenly distributed hashmap. Instead, hash the pointer
|
||||
// like most other types.
|
||||
return hashmapHash(ptr, x.Type().Size())
|
||||
return hashmapHash(ptr, x.RawType().Size())
|
||||
case reflect.Array:
|
||||
var hash uint32
|
||||
for i := 0; i < x.Len(); i++ {
|
||||
|
||||
@@ -31,18 +31,21 @@ func interfaceEqual(x, y interface{}) bool {
|
||||
}
|
||||
|
||||
func reflectValueEqual(x, y reflect.Value) bool {
|
||||
if x.Type() == 0 || y.Type() == 0 {
|
||||
// Note: doing a x.Type() == y.Type() comparison would not work here as that
|
||||
// would introduce an infinite recursion: comparing two reflect.Type values
|
||||
// is done with this reflectValueEqual runtime call.
|
||||
if x.RawType() == 0 || y.RawType() == 0 {
|
||||
// One of them is nil.
|
||||
return x.Type() == y.Type()
|
||||
return x.RawType() == y.RawType()
|
||||
}
|
||||
|
||||
if x.Type() != y.Type() {
|
||||
if x.RawType() != y.RawType() {
|
||||
// The type is not the same, which means the interfaces are definitely
|
||||
// not the same.
|
||||
return false
|
||||
}
|
||||
|
||||
switch x.Type().Kind() {
|
||||
switch x.RawType().Kind() {
|
||||
case reflect.Bool:
|
||||
return x.Bool() == y.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
|
||||
Reference in New Issue
Block a user