aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r--src/reflect/value.go33
1 files changed, 23 insertions, 10 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index a14131e1f8..24eab6a2c6 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -90,6 +90,7 @@ func (f flag) ro() flag {
// pointer returns the underlying pointer represented by v.
// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
+// if v.Kind() == Ptr, the base type must not be go:notinheap.
func (v Value) pointer() unsafe.Pointer {
if v.typ.size != ptrSize || !v.typ.pointers() {
panic("can't call pointer on a non-pointer Value")
@@ -635,10 +636,11 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *fu
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if uint(i) >= uint(len(tt.methods)) {
+ ttmethods := tt.methods()
+ if uint(i) >= uint(len(ttmethods)) {
panic("reflect: internal error: invalid method index")
}
- m := &tt.methods[i]
+ m := &ttmethods[i]
if !tt.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
@@ -812,7 +814,7 @@ func (v Value) Elem() Value {
switch k {
case Interface:
var eface interface{}
- if v.typ.NumMethod() == 0 {
+ if isEmptyIface(v.typ) {
eface = *(*interface{})(v.ptr)
} else {
eface = (interface{})(*(*interface {
@@ -1033,7 +1035,7 @@ func valueInterface(v Value, safe bool) interface{} {
// Special case: return the element inside the interface.
// Empty interface has one layout, all interfaces with
// methods have a second layout.
- if v.NumMethod() == 0 {
+ if isEmptyIface(v.typ) {
return *(*interface{})(v.ptr)
}
return *(*interface {
@@ -1452,7 +1454,16 @@ func (v Value) Pointer() uintptr {
// TODO: deprecate
k := v.kind()
switch k {
- case Chan, Map, Ptr, UnsafePointer:
+ case Ptr:
+ if v.typ.ptrdata == 0 {
+ // Handle pointers to go:notinheap types directly,
+ // so we never materialize such pointers as an
+ // unsafe.Pointer. (Such pointers are always indirect.)
+ // See issue 42076.
+ return *(*uintptr)(v.ptr)
+ }
+ fallthrough
+ case Chan, Map, UnsafePointer:
return uintptr(v.pointer())
case Func:
if v.flag&flagMethod != 0 {
@@ -1908,10 +1919,11 @@ func (v Value) Type() Type {
if v.typ.Kind() == Interface {
// Method on interface.
tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if uint(i) >= uint(len(tt.methods)) {
+ ttmethods := tt.methods()
+ if uint(i) >= uint(len(ttmethods)) {
panic("reflect: internal error: invalid method index")
}
- m := &tt.methods[i]
+ m := &ttmethods[i]
return v.typ.typeOff(m.typ)
}
// Method on concrete type.
@@ -2429,7 +2441,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
return Value{dst, nil, flag(Interface)}
}
x := valueInterface(v, false)
- if dst.NumMethod() == 0 {
+ if isEmptyIface(dst) {
*(*interface{})(target) = x
} else {
ifaceE2I(dst, x, target)
@@ -2718,10 +2730,11 @@ func cvtDirect(v Value, typ Type) Value {
func cvtT2I(v Value, typ Type) Value {
target := unsafe_New(typ.common())
x := valueInterface(v, false)
- if typ.NumMethod() == 0 {
+ rt := typ.(*rtype)
+ if isEmptyIface(rt) {
*(*interface{})(target) = x
} else {
- ifaceE2I(typ.(*rtype), x, target)
+ ifaceE2I(rt, x, target)
}
return Value{typ.common(), target, v.flag.ro() | flagIndir | flag(Interface)}
}