mirror of
https://github.com/golang/go
synced 2025-05-05 03:21:36 +00:00
internal/reflectlite: common up types, remove code
Change-Id: I4d3ef025b935e52c47896f69814ba2f1a504d749 Reviewed-on: https://go-review.googlesource.com/c/go/+/489375 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: David Chase <drchase@google.com>
This commit is contained in:
src/internal/reflectlite
@ -15,17 +15,17 @@ func Field(v Value, i int) Value {
|
||||
panic(&ValueError{"reflect.Value.Field", v.kind()})
|
||||
}
|
||||
tt := (*structType)(unsafe.Pointer(v.typ))
|
||||
if uint(i) >= uint(len(tt.fields)) {
|
||||
if uint(i) >= uint(len(tt.Fields)) {
|
||||
panic("reflect: Field index out of range")
|
||||
}
|
||||
field := &tt.fields[i]
|
||||
typ := field.typ
|
||||
field := &tt.Fields[i]
|
||||
typ := field.Typ
|
||||
|
||||
// Inherit permission bits from v, but clear flagEmbedRO.
|
||||
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
|
||||
// Using an unexported field forces flagRO.
|
||||
if !field.name.isExported() {
|
||||
if field.embedded() {
|
||||
if !field.Name.IsExported() {
|
||||
if field.Embedded() {
|
||||
fl |= flagEmbedRO
|
||||
} else {
|
||||
fl |= flagStickyRO
|
||||
@ -36,27 +36,27 @@ func Field(v Value, i int) Value {
|
||||
// In the former case, we want v.ptr + offset.
|
||||
// In the latter case, we must have field.offset = 0,
|
||||
// so v.ptr + field.offset is still the correct address.
|
||||
ptr := add(v.ptr, field.offset, "same as non-reflect &v.field")
|
||||
ptr := add(v.ptr, field.Offset, "same as non-reflect &v.field")
|
||||
return Value{typ, ptr, fl}
|
||||
}
|
||||
|
||||
func TField(typ Type, i int) Type {
|
||||
t := typ.(*rtype)
|
||||
t := typ.(rtype)
|
||||
if t.Kind() != Struct {
|
||||
panic("reflect: Field of non-struct type")
|
||||
}
|
||||
tt := (*structType)(unsafe.Pointer(t))
|
||||
tt := (*structType)(unsafe.Pointer(t.Type))
|
||||
|
||||
return StructFieldType(tt, i)
|
||||
}
|
||||
|
||||
// Field returns the i'th struct field.
|
||||
func StructFieldType(t *structType, i int) Type {
|
||||
if i < 0 || i >= len(t.fields) {
|
||||
if i < 0 || i >= len(t.Fields) {
|
||||
panic("reflect: Field index out of bounds")
|
||||
}
|
||||
p := &t.fields[i]
|
||||
return toType(p.typ)
|
||||
p := &t.Fields[i]
|
||||
return toType(p.Typ)
|
||||
}
|
||||
|
||||
// Zero returns a Value representing the zero value for the specified type.
|
||||
@ -68,7 +68,7 @@ func Zero(typ Type) Value {
|
||||
if typ == nil {
|
||||
panic("reflect: Zero(nil)")
|
||||
}
|
||||
t := typ.(*rtype)
|
||||
t := typ.common()
|
||||
fl := flag(t.Kind())
|
||||
if ifaceIndir(t) {
|
||||
return Value{t, unsafe_New(t), fl | flagIndir}
|
||||
@ -105,11 +105,11 @@ func FirstMethodNameBytes(t Type) *byte {
|
||||
panic("type has no methods")
|
||||
}
|
||||
m := ut.Methods()[0]
|
||||
mname := t.(*rtype).nameOff(m.Name)
|
||||
if *mname.data(0, "name flag field")&(1<<2) == 0 {
|
||||
mname := t.(rtype).nameOff(m.Name)
|
||||
if *mname.DataChecked(0, "name flag field")&(1<<2) == 0 {
|
||||
panic("method name does not have pkgPath *string")
|
||||
}
|
||||
return mname.bytes
|
||||
return mname.Bytes
|
||||
}
|
||||
|
||||
type Buffer struct {
|
||||
|
@ -31,7 +31,7 @@ func Swapper(slice any) func(i, j int) {
|
||||
}
|
||||
}
|
||||
|
||||
typ := v.Type().Elem().(*rtype)
|
||||
typ := v.Type().Elem().common()
|
||||
size := typ.Size()
|
||||
hasPtr := typ.PtrBytes != 0
|
||||
|
||||
|
@ -63,7 +63,7 @@ type Type interface {
|
||||
// It panics if the type's Kind is not Ptr.
|
||||
Elem() Type
|
||||
|
||||
common() *rtype
|
||||
common() *abi.Type
|
||||
uncommon() *uncommonType
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ type typeOff = abi.TypeOff
|
||||
type textOff = abi.TextOff
|
||||
|
||||
type rtype struct {
|
||||
abi.Type
|
||||
*abi.Type
|
||||
}
|
||||
|
||||
// uncommonType is present only for defined types or types with methods
|
||||
@ -101,88 +101,38 @@ type rtype struct {
|
||||
// to describe a non-defined type with no methods.
|
||||
type uncommonType = abi.UncommonType
|
||||
|
||||
// chanDir represents a channel type's direction.
|
||||
type chanDir int
|
||||
|
||||
const (
|
||||
recvDir chanDir = 1 << iota // <-chan
|
||||
sendDir // chan<-
|
||||
bothDir = recvDir | sendDir // chan
|
||||
)
|
||||
|
||||
// arrayType represents a fixed array type.
|
||||
type arrayType = abi.ArrayType
|
||||
|
||||
// chanType represents a channel type.
|
||||
type chanType = abi.ChanType
|
||||
|
||||
// funcType represents a function type.
|
||||
//
|
||||
// A *rtype for each in and out parameter is stored in an array that
|
||||
// directly follows the funcType (and possibly its uncommonType). So
|
||||
// a function type with one method, one input, and one output is:
|
||||
//
|
||||
// struct {
|
||||
// funcType
|
||||
// uncommonType
|
||||
// [2]*rtype // [0] is in, [1] is out
|
||||
// }
|
||||
type funcType struct {
|
||||
rtype
|
||||
inCount uint16
|
||||
outCount uint16 // top bit is set if last input parameter is ...
|
||||
}
|
||||
type funcType = abi.FuncType
|
||||
|
||||
// interfaceType represents an interface type.
|
||||
type interfaceType struct {
|
||||
rtype
|
||||
pkgPath name // import path
|
||||
methods []abi.Imethod // sorted by hash
|
||||
}
|
||||
type interfaceType = abi.InterfaceType
|
||||
|
||||
// mapType represents a map type.
|
||||
type mapType struct {
|
||||
rtype
|
||||
key *rtype // map key type
|
||||
elem *rtype // map element (value) type
|
||||
bucket *rtype // internal bucket structure
|
||||
Key *abi.Type // map key type
|
||||
Elem *abi.Type // map element (value) type
|
||||
Bucket *abi.Type // internal bucket structure
|
||||
// function for hashing keys (ptr to key, seed) -> hash
|
||||
hasher func(unsafe.Pointer, uintptr) uintptr
|
||||
keysize uint8 // size of key slot
|
||||
valuesize uint8 // size of value slot
|
||||
bucketsize uint16 // size of bucket
|
||||
flags uint32
|
||||
Hasher func(unsafe.Pointer, uintptr) uintptr
|
||||
KeySize uint8 // size of key slot
|
||||
ValueSize uint8 // size of value slot
|
||||
BucketSize uint16 // size of bucket
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// ptrType represents a pointer type.
|
||||
type ptrType struct {
|
||||
rtype
|
||||
elem *rtype // pointer element (pointed at) type
|
||||
}
|
||||
type ptrType = abi.PtrType
|
||||
|
||||
// sliceType represents a slice type.
|
||||
type sliceType struct {
|
||||
rtype
|
||||
elem *rtype // slice element type
|
||||
}
|
||||
|
||||
// Struct field
|
||||
type structField struct {
|
||||
name name // name is always non-empty
|
||||
typ *rtype // type of field
|
||||
offset uintptr // byte offset of field
|
||||
}
|
||||
|
||||
func (f *structField) embedded() bool {
|
||||
return f.name.embedded()
|
||||
}
|
||||
type sliceType = abi.SliceType
|
||||
|
||||
// structType represents a struct type.
|
||||
type structType struct {
|
||||
rtype
|
||||
pkgPath name
|
||||
fields []structField // sorted by offset
|
||||
}
|
||||
type structType = abi.StructType
|
||||
|
||||
// name is an encoded type name with optional extra data.
|
||||
//
|
||||
@ -257,21 +207,21 @@ func (n name) tag() string {
|
||||
return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
|
||||
}
|
||||
|
||||
func (n name) pkgPath() string {
|
||||
if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
|
||||
func pkgPath(n abi.Name) string {
|
||||
if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
|
||||
return ""
|
||||
}
|
||||
i, l := n.readVarint(1)
|
||||
i, l := n.ReadVarint(1)
|
||||
off := 1 + i + l
|
||||
if n.hasTag() {
|
||||
i2, l2 := n.readVarint(off)
|
||||
if n.HasTag() {
|
||||
i2, l2 := n.ReadVarint(off)
|
||||
off += i2 + l2
|
||||
}
|
||||
var nameOff int32
|
||||
// Note that this field may not be aligned in memory,
|
||||
// so we cannot use a direct int32 assignment here.
|
||||
copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
|
||||
pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
|
||||
copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
|
||||
pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
|
||||
return pkgPathName.name()
|
||||
}
|
||||
|
||||
@ -290,31 +240,29 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
|
||||
// Implemented in the runtime package.
|
||||
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
|
||||
|
||||
func (t *rtype) nameOff(off nameOff) name {
|
||||
return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
|
||||
func (t rtype) nameOff(off nameOff) abi.Name {
|
||||
return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
|
||||
}
|
||||
|
||||
func (t *rtype) typeOff(off typeOff) *rtype {
|
||||
return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
|
||||
func (t rtype) typeOff(off typeOff) *abi.Type {
|
||||
return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
|
||||
}
|
||||
|
||||
func (t *rtype) uncommon() *uncommonType {
|
||||
func (t rtype) uncommon() *uncommonType {
|
||||
return t.Uncommon()
|
||||
}
|
||||
|
||||
func (t *rtype) String() string {
|
||||
s := t.nameOff(t.Str).name()
|
||||
func (t rtype) String() string {
|
||||
s := t.nameOff(t.Str).Name()
|
||||
if t.TFlag&abi.TFlagExtraStar != 0 {
|
||||
return s[1:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (t *rtype) pointers() bool { return t.PtrBytes != 0 }
|
||||
func (t rtype) common() *abi.Type { return t.Type }
|
||||
|
||||
func (t *rtype) common() *rtype { return t }
|
||||
|
||||
func (t *rtype) exportedMethods() []abi.Method {
|
||||
func (t rtype) exportedMethods() []abi.Method {
|
||||
ut := t.uncommon()
|
||||
if ut == nil {
|
||||
return nil
|
||||
@ -322,15 +270,15 @@ func (t *rtype) exportedMethods() []abi.Method {
|
||||
return ut.ExportedMethods()
|
||||
}
|
||||
|
||||
func (t *rtype) NumMethod() int {
|
||||
if t.Kind() == Interface {
|
||||
tt := (*interfaceType)(unsafe.Pointer(t))
|
||||
func (t rtype) NumMethod() int {
|
||||
tt := t.Type.InterfaceType()
|
||||
if tt != nil {
|
||||
return tt.NumMethod()
|
||||
}
|
||||
return len(t.exportedMethods())
|
||||
}
|
||||
|
||||
func (t *rtype) PkgPath() string {
|
||||
func (t rtype) PkgPath() string {
|
||||
if t.TFlag&abi.TFlagNamed == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -338,15 +286,11 @@ func (t *rtype) PkgPath() string {
|
||||
if ut == nil {
|
||||
return ""
|
||||
}
|
||||
return t.nameOff(ut.PkgPath).name()
|
||||
return t.nameOff(ut.PkgPath).Name()
|
||||
}
|
||||
|
||||
func (t *rtype) hasName() bool {
|
||||
return t.TFlag&abi.TFlagNamed != 0
|
||||
}
|
||||
|
||||
func (t *rtype) Name() string {
|
||||
if !t.hasName() {
|
||||
func (t rtype) Name() string {
|
||||
if !t.HasName() {
|
||||
return ""
|
||||
}
|
||||
s := t.String()
|
||||
@ -364,116 +308,76 @@ func (t *rtype) Name() string {
|
||||
return s[i+1:]
|
||||
}
|
||||
|
||||
func (t *rtype) chanDir() chanDir {
|
||||
if t.Kind() != abi.Chan {
|
||||
panic("reflect: chanDir of non-chan type")
|
||||
func toRType(t *abi.Type) rtype {
|
||||
return rtype{t}
|
||||
}
|
||||
|
||||
func elem(t *abi.Type) *abi.Type {
|
||||
et := t.Elem()
|
||||
if et != nil {
|
||||
return et
|
||||
}
|
||||
tt := (*chanType)(unsafe.Pointer(t))
|
||||
return chanDir(tt.Dir)
|
||||
panic("reflect: Elem of invalid type " + toRType(t).String())
|
||||
}
|
||||
|
||||
func toRType(t *abi.Type) *rtype {
|
||||
return (*rtype)(unsafe.Pointer(t))
|
||||
func (t rtype) Elem() Type {
|
||||
return toType(elem(t.common()))
|
||||
}
|
||||
|
||||
func (t *rtype) Elem() Type {
|
||||
switch t.Kind() {
|
||||
case abi.Array:
|
||||
tt := (*arrayType)(unsafe.Pointer(t))
|
||||
return toType(toRType(tt.Elem))
|
||||
case abi.Chan:
|
||||
tt := (*chanType)(unsafe.Pointer(t))
|
||||
return toType(toRType(tt.Elem))
|
||||
case abi.Map:
|
||||
tt := (*mapType)(unsafe.Pointer(t))
|
||||
return toType(tt.elem)
|
||||
case abi.Pointer:
|
||||
tt := (*ptrType)(unsafe.Pointer(t))
|
||||
return toType(tt.elem)
|
||||
case abi.Slice:
|
||||
tt := (*sliceType)(unsafe.Pointer(t))
|
||||
return toType(tt.elem)
|
||||
}
|
||||
panic("reflect: Elem of invalid type")
|
||||
}
|
||||
|
||||
func (t *rtype) In(i int) Type {
|
||||
if t.Kind() != abi.Func {
|
||||
func (t rtype) In(i int) Type {
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: In of non-func type")
|
||||
}
|
||||
tt := (*funcType)(unsafe.Pointer(t))
|
||||
return toType(tt.in()[i])
|
||||
return toType(tt.InSlice()[i])
|
||||
}
|
||||
|
||||
func (t *rtype) Key() Type {
|
||||
if t.Kind() != abi.Map {
|
||||
func (t rtype) Key() Type {
|
||||
tt := t.Type.MapType()
|
||||
if tt == nil {
|
||||
panic("reflect: Key of non-map type")
|
||||
}
|
||||
tt := (*mapType)(unsafe.Pointer(t))
|
||||
return toType(tt.key)
|
||||
return toType(tt.Key)
|
||||
}
|
||||
|
||||
func (t *rtype) Len() int {
|
||||
if t.Kind() != abi.Array {
|
||||
func (t rtype) Len() int {
|
||||
tt := t.Type.ArrayType()
|
||||
if tt == nil {
|
||||
panic("reflect: Len of non-array type")
|
||||
}
|
||||
tt := (*arrayType)(unsafe.Pointer(t))
|
||||
return int(tt.Len)
|
||||
}
|
||||
|
||||
func (t *rtype) NumField() int {
|
||||
if t.Kind() != abi.Struct {
|
||||
func (t rtype) NumField() int {
|
||||
tt := t.Type.StructType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumField of non-struct type")
|
||||
}
|
||||
tt := (*structType)(unsafe.Pointer(t))
|
||||
return len(tt.fields)
|
||||
return len(tt.Fields)
|
||||
}
|
||||
|
||||
func (t *rtype) NumIn() int {
|
||||
if t.Kind() != abi.Func {
|
||||
func (t rtype) NumIn() int {
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumIn of non-func type")
|
||||
}
|
||||
tt := (*funcType)(unsafe.Pointer(t))
|
||||
return int(tt.inCount)
|
||||
return int(tt.InCount)
|
||||
}
|
||||
|
||||
func (t *rtype) NumOut() int {
|
||||
if t.Kind() != abi.Func {
|
||||
func (t rtype) NumOut() int {
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: NumOut of non-func type")
|
||||
}
|
||||
tt := (*funcType)(unsafe.Pointer(t))
|
||||
return len(tt.out())
|
||||
return tt.NumOut()
|
||||
}
|
||||
|
||||
func (t *rtype) Out(i int) Type {
|
||||
if t.Kind() != abi.Func {
|
||||
func (t rtype) Out(i int) Type {
|
||||
tt := t.Type.FuncType()
|
||||
if tt == nil {
|
||||
panic("reflect: Out of non-func type")
|
||||
}
|
||||
tt := (*funcType)(unsafe.Pointer(t))
|
||||
return toType(tt.out()[i])
|
||||
}
|
||||
|
||||
func (t *funcType) in() []*rtype {
|
||||
uadd := unsafe.Sizeof(*t)
|
||||
if t.TFlag&abi.TFlagUncommon != 0 {
|
||||
uadd += unsafe.Sizeof(uncommonType{})
|
||||
}
|
||||
if t.inCount == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
|
||||
}
|
||||
|
||||
func (t *funcType) out() []*rtype {
|
||||
uadd := unsafe.Sizeof(*t)
|
||||
if t.TFlag&abi.TFlagUncommon != 0 {
|
||||
uadd += unsafe.Sizeof(uncommonType{})
|
||||
}
|
||||
outCount := t.outCount & (1<<15 - 1)
|
||||
if outCount == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
|
||||
return toType(tt.OutSlice()[i])
|
||||
}
|
||||
|
||||
// add returns p+x.
|
||||
@ -487,9 +391,6 @@ func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(p) + x)
|
||||
}
|
||||
|
||||
// NumMethod returns the number of interface methods in the type's method set.
|
||||
func (t *interfaceType) NumMethod() int { return len(t.methods) }
|
||||
|
||||
// TypeOf returns the reflection Type that represents the dynamic type of i.
|
||||
// If i is a nil interface value, TypeOf returns nil.
|
||||
func TypeOf(i any) Type {
|
||||
@ -497,37 +398,40 @@ func TypeOf(i any) Type {
|
||||
return toType(eface.typ)
|
||||
}
|
||||
|
||||
func (t *rtype) Implements(u Type) bool {
|
||||
func (t rtype) Implements(u Type) bool {
|
||||
if u == nil {
|
||||
panic("reflect: nil type passed to Type.Implements")
|
||||
}
|
||||
if u.Kind() != Interface {
|
||||
panic("reflect: non-interface type passed to Type.Implements")
|
||||
}
|
||||
return implements(u.(*rtype), t)
|
||||
return implements(u.common(), t.common())
|
||||
}
|
||||
|
||||
func (t *rtype) AssignableTo(u Type) bool {
|
||||
func (t rtype) AssignableTo(u Type) bool {
|
||||
if u == nil {
|
||||
panic("reflect: nil type passed to Type.AssignableTo")
|
||||
}
|
||||
uu := u.(*rtype)
|
||||
return directlyAssignable(uu, t) || implements(uu, t)
|
||||
uu := u.common()
|
||||
tt := t.common()
|
||||
return directlyAssignable(uu, tt) || implements(uu, tt)
|
||||
}
|
||||
|
||||
func (t *rtype) Comparable() bool {
|
||||
func (t rtype) Comparable() bool {
|
||||
return t.Equal != nil
|
||||
}
|
||||
|
||||
// implements reports whether the type V implements the interface type T.
|
||||
func implements(T, V *rtype) bool {
|
||||
if T.Kind() != Interface {
|
||||
func implements(T, V *abi.Type) bool {
|
||||
t := T.InterfaceType()
|
||||
if t == nil {
|
||||
return false
|
||||
}
|
||||
t := (*interfaceType)(unsafe.Pointer(T))
|
||||
if len(t.methods) == 0 {
|
||||
if len(t.Methods) == 0 {
|
||||
return true
|
||||
}
|
||||
rT := toRType(T)
|
||||
rV := toRType(V)
|
||||
|
||||
// The same algorithm applies in both cases, but the
|
||||
// method tables for an interface type and a concrete type
|
||||
@ -544,26 +448,26 @@ func implements(T, V *rtype) bool {
|
||||
if V.Kind() == Interface {
|
||||
v := (*interfaceType)(unsafe.Pointer(V))
|
||||
i := 0
|
||||
for j := 0; j < len(v.methods); j++ {
|
||||
tm := &t.methods[i]
|
||||
tmName := t.nameOff(tm.Name)
|
||||
vm := &v.methods[j]
|
||||
vmName := V.nameOff(vm.Name)
|
||||
if vmName.name() == tmName.name() && V.typeOff(vm.Typ) == t.typeOff(tm.Typ) {
|
||||
if !tmName.isExported() {
|
||||
tmPkgPath := tmName.pkgPath()
|
||||
for j := 0; j < len(v.Methods); j++ {
|
||||
tm := &t.Methods[i]
|
||||
tmName := rT.nameOff(tm.Name)
|
||||
vm := &v.Methods[j]
|
||||
vmName := rV.nameOff(vm.Name)
|
||||
if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
|
||||
if !tmName.IsExported() {
|
||||
tmPkgPath := pkgPath(tmName)
|
||||
if tmPkgPath == "" {
|
||||
tmPkgPath = t.pkgPath.name()
|
||||
tmPkgPath = t.PkgPath.Name()
|
||||
}
|
||||
vmPkgPath := vmName.pkgPath()
|
||||
vmPkgPath := pkgPath(vmName)
|
||||
if vmPkgPath == "" {
|
||||
vmPkgPath = v.pkgPath.name()
|
||||
vmPkgPath = v.PkgPath.Name()
|
||||
}
|
||||
if tmPkgPath != vmPkgPath {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if i++; i >= len(t.methods) {
|
||||
if i++; i >= len(t.Methods) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -571,32 +475,32 @@ func implements(T, V *rtype) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v := V.uncommon()
|
||||
v := V.Uncommon()
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
i := 0
|
||||
vmethods := v.Methods()
|
||||
for j := 0; j < int(v.Mcount); j++ {
|
||||
tm := &t.methods[i]
|
||||
tmName := t.nameOff(tm.Name)
|
||||
tm := &t.Methods[i]
|
||||
tmName := rT.nameOff(tm.Name)
|
||||
vm := vmethods[j]
|
||||
vmName := V.nameOff(vm.Name)
|
||||
if vmName.name() == tmName.name() && V.typeOff(vm.Mtyp) == t.typeOff(tm.Typ) {
|
||||
if !tmName.isExported() {
|
||||
tmPkgPath := tmName.pkgPath()
|
||||
vmName := rV.nameOff(vm.Name)
|
||||
if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
|
||||
if !tmName.IsExported() {
|
||||
tmPkgPath := pkgPath(tmName)
|
||||
if tmPkgPath == "" {
|
||||
tmPkgPath = t.pkgPath.name()
|
||||
tmPkgPath = t.PkgPath.Name()
|
||||
}
|
||||
vmPkgPath := vmName.pkgPath()
|
||||
vmPkgPath := pkgPath(vmName)
|
||||
if vmPkgPath == "" {
|
||||
vmPkgPath = V.nameOff(v.PkgPath).name()
|
||||
vmPkgPath = rV.nameOff(v.PkgPath).Name()
|
||||
}
|
||||
if tmPkgPath != vmPkgPath {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if i++; i >= len(t.methods) {
|
||||
if i++; i >= len(t.Methods) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -609,7 +513,7 @@ func implements(T, V *rtype) bool {
|
||||
// https://golang.org/doc/go_spec.html#Assignability
|
||||
// Ignoring the interface rules (implemented elsewhere)
|
||||
// and the ideal constant rules (no ideal constants at run time).
|
||||
func directlyAssignable(T, V *rtype) bool {
|
||||
func directlyAssignable(T, V *abi.Type) bool {
|
||||
// x's type V is identical to T?
|
||||
if T == V {
|
||||
return true
|
||||
@ -617,7 +521,7 @@ func directlyAssignable(T, V *rtype) bool {
|
||||
|
||||
// Otherwise at least one of T and V must not be defined
|
||||
// and they must have the same kind.
|
||||
if T.hasName() && V.hasName() || T.Kind() != V.Kind() {
|
||||
if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -625,19 +529,19 @@ func directlyAssignable(T, V *rtype) bool {
|
||||
return haveIdenticalUnderlyingType(T, V, true)
|
||||
}
|
||||
|
||||
func haveIdenticalType(T, V Type, cmpTags bool) bool {
|
||||
func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
|
||||
if cmpTags {
|
||||
return T == V
|
||||
}
|
||||
|
||||
if T.Name() != V.Name() || T.Kind() != V.Kind() {
|
||||
if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
|
||||
return false
|
||||
}
|
||||
|
||||
return haveIdenticalUnderlyingType(T.common(), V.common(), false)
|
||||
return haveIdenticalUnderlyingType(T, V, false)
|
||||
}
|
||||
|
||||
func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
|
||||
if T == V {
|
||||
return true
|
||||
}
|
||||
@ -662,17 +566,17 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
// Special case:
|
||||
// x is a bidirectional channel value, T is a channel type,
|
||||
// and x's type V and T have identical element types.
|
||||
if V.chanDir() == bothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
|
||||
if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise continue test for identical underlying type.
|
||||
return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
|
||||
|
||||
case abi.Func:
|
||||
t := (*funcType)(unsafe.Pointer(T))
|
||||
v := (*funcType)(unsafe.Pointer(V))
|
||||
if t.outCount != v.outCount || t.inCount != v.inCount {
|
||||
if t.OutCount != v.OutCount || t.InCount != v.InCount {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < t.NumIn(); i++ {
|
||||
@ -690,7 +594,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
case Interface:
|
||||
t := (*interfaceType)(unsafe.Pointer(T))
|
||||
v := (*interfaceType)(unsafe.Pointer(V))
|
||||
if len(t.methods) == 0 && len(v.methods) == 0 {
|
||||
if len(t.Methods) == 0 && len(v.Methods) == 0 {
|
||||
return true
|
||||
}
|
||||
// Might have the same methods but still
|
||||
@ -706,28 +610,28 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
case abi.Struct:
|
||||
t := (*structType)(unsafe.Pointer(T))
|
||||
v := (*structType)(unsafe.Pointer(V))
|
||||
if len(t.fields) != len(v.fields) {
|
||||
if len(t.Fields) != len(v.Fields) {
|
||||
return false
|
||||
}
|
||||
if t.pkgPath.name() != v.pkgPath.name() {
|
||||
if t.PkgPath.Name() != v.PkgPath.Name() {
|
||||
return false
|
||||
}
|
||||
for i := range t.fields {
|
||||
tf := &t.fields[i]
|
||||
vf := &v.fields[i]
|
||||
if tf.name.name() != vf.name.name() {
|
||||
for i := range t.Fields {
|
||||
tf := &t.Fields[i]
|
||||
vf := &v.Fields[i]
|
||||
if tf.Name.Name() != vf.Name.Name() {
|
||||
return false
|
||||
}
|
||||
if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
|
||||
if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
|
||||
return false
|
||||
}
|
||||
if cmpTags && tf.name.tag() != vf.name.tag() {
|
||||
if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
|
||||
return false
|
||||
}
|
||||
if tf.offset != vf.offset {
|
||||
if tf.Offset != vf.Offset {
|
||||
return false
|
||||
}
|
||||
if tf.embedded() != vf.embedded() {
|
||||
if tf.Embedded() != vf.Embedded() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -737,24 +641,19 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type structTypeUncommon struct {
|
||||
structType
|
||||
u uncommonType
|
||||
}
|
||||
|
||||
// toType converts from a *rtype to a Type that can be returned
|
||||
// to the client of package reflect. In gc, the only concern is that
|
||||
// a nil *rtype must be replaced by a nil Type, but in gccgo this
|
||||
// function takes care of ensuring that multiple *rtype for the same
|
||||
// type are coalesced into a single Type.
|
||||
func toType(t *rtype) Type {
|
||||
func toType(t *abi.Type) Type {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
return t
|
||||
return toRType(t)
|
||||
}
|
||||
|
||||
// ifaceIndir reports whether t is stored indirectly in an interface value.
|
||||
func ifaceIndir(t *rtype) bool {
|
||||
func ifaceIndir(t *abi.Type) bool {
|
||||
return t.Kind_&abi.KindDirectIface == 0
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import (
|
||||
// they represent.
|
||||
type Value struct {
|
||||
// typ holds the type of the value represented by a Value.
|
||||
typ *rtype
|
||||
typ *abi.Type
|
||||
|
||||
// Pointer-valued data or, if flagIndir is set, pointer to data.
|
||||
// Valid when either flagIndir is set or typ.pointers() is true.
|
||||
@ -90,7 +90,7 @@ func (f flag) ro() flag {
|
||||
// pointer returns the underlying pointer represented by v.
|
||||
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
|
||||
func (v Value) pointer() unsafe.Pointer {
|
||||
if v.typ.Size() != goarch.PtrSize || !v.typ.pointers() {
|
||||
if v.typ.Size() != goarch.PtrSize || !v.typ.Pointers() {
|
||||
panic("can't call pointer on a non-pointer Value")
|
||||
}
|
||||
if v.flag&flagIndir != 0 {
|
||||
@ -179,7 +179,7 @@ func methodName() string {
|
||||
|
||||
// emptyInterface is the header for an interface{} value.
|
||||
type emptyInterface struct {
|
||||
typ *rtype
|
||||
typ *abi.Type
|
||||
word unsafe.Pointer
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ func (v Value) Elem() Value {
|
||||
return Value{}
|
||||
}
|
||||
tt := (*ptrType)(unsafe.Pointer(v.typ))
|
||||
typ := tt.elem
|
||||
typ := tt.Elem
|
||||
fl := v.flag&flagRO | flagIndir | flagAddr
|
||||
fl |= flag(typ.Kind())
|
||||
return Value{typ, ptr, fl}
|
||||
@ -380,7 +380,7 @@ func (v Value) Type() Type {
|
||||
panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
|
||||
}
|
||||
// Method values not supported.
|
||||
return v.typ
|
||||
return toRType(v.typ)
|
||||
}
|
||||
|
||||
/*
|
||||
@ -388,7 +388,7 @@ func (v Value) Type() Type {
|
||||
*/
|
||||
|
||||
// implemented in package runtime
|
||||
func unsafe_New(*rtype) unsafe.Pointer
|
||||
func unsafe_New(*abi.Type) unsafe.Pointer
|
||||
|
||||
// ValueOf returns a new Value initialized to the concrete value
|
||||
// stored in the interface i. ValueOf(nil) returns the zero Value.
|
||||
@ -409,7 +409,7 @@ func ValueOf(i any) Value {
|
||||
// assignTo returns a value v that can be assigned directly to typ.
|
||||
// It panics if v is not assignable to typ.
|
||||
// For a conversion to an interface type, target is a suggested scratch space to use.
|
||||
func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
|
||||
func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Value {
|
||||
// if v.flag&flagMethod != 0 {
|
||||
// v = makeMethodValue(context, v)
|
||||
// }
|
||||
@ -442,7 +442,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
|
||||
}
|
||||
|
||||
// Failed.
|
||||
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
|
||||
panic(context + ": value of type " + toRType(v.typ).String() + " is not assignable to type " + toRType(dst).String())
|
||||
}
|
||||
|
||||
// arrayAt returns the i-th element of p,
|
||||
@ -456,12 +456,12 @@ func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Po
|
||||
return add(p, uintptr(i)*eltSize, "i < len")
|
||||
}
|
||||
|
||||
func ifaceE2I(t *rtype, src any, dst unsafe.Pointer)
|
||||
func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
|
||||
|
||||
// typedmemmove copies a value of type t to dst from src.
|
||||
//
|
||||
//go:noescape
|
||||
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
|
||||
func typedmemmove(t *abi.Type, dst, src unsafe.Pointer)
|
||||
|
||||
// Dummy annotation marking that the value x escapes,
|
||||
// for use in cases where the reflect code is so clever that
|
||||
|
Reference in New Issue
Block a user