1
0
mirror of https://github.com/golang/go synced 2024-09-29 04:24:36 -06: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:
David Chase 2023-04-26 15:30:04 -04:00
parent 2e93fe0a9f
commit 3ee12d5702
4 changed files with 161 additions and 262 deletions

View File

@ -15,17 +15,17 @@ func Field(v Value, i int) Value {
panic(&ValueError{"reflect.Value.Field", v.kind()}) panic(&ValueError{"reflect.Value.Field", v.kind()})
} }
tt := (*structType)(unsafe.Pointer(v.typ)) 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") panic("reflect: Field index out of range")
} }
field := &tt.fields[i] field := &tt.Fields[i]
typ := field.typ typ := field.Typ
// Inherit permission bits from v, but clear flagEmbedRO. // Inherit permission bits from v, but clear flagEmbedRO.
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind()) fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO. // Using an unexported field forces flagRO.
if !field.name.isExported() { if !field.Name.IsExported() {
if field.embedded() { if field.Embedded() {
fl |= flagEmbedRO fl |= flagEmbedRO
} else { } else {
fl |= flagStickyRO fl |= flagStickyRO
@ -36,27 +36,27 @@ func Field(v Value, i int) Value {
// In the former case, we want v.ptr + offset. // In the former case, we want v.ptr + offset.
// In the latter case, we must have field.offset = 0, // In the latter case, we must have field.offset = 0,
// so v.ptr + field.offset is still the correct address. // 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} return Value{typ, ptr, fl}
} }
func TField(typ Type, i int) Type { func TField(typ Type, i int) Type {
t := typ.(*rtype) t := typ.(rtype)
if t.Kind() != Struct { if t.Kind() != Struct {
panic("reflect: Field of non-struct type") panic("reflect: Field of non-struct type")
} }
tt := (*structType)(unsafe.Pointer(t)) tt := (*structType)(unsafe.Pointer(t.Type))
return StructFieldType(tt, i) return StructFieldType(tt, i)
} }
// Field returns the i'th struct field. // Field returns the i'th struct field.
func StructFieldType(t *structType, i int) Type { 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") panic("reflect: Field index out of bounds")
} }
p := &t.fields[i] p := &t.Fields[i]
return toType(p.typ) return toType(p.Typ)
} }
// Zero returns a Value representing the zero value for the specified type. // Zero returns a Value representing the zero value for the specified type.
@ -68,7 +68,7 @@ func Zero(typ Type) Value {
if typ == nil { if typ == nil {
panic("reflect: Zero(nil)") panic("reflect: Zero(nil)")
} }
t := typ.(*rtype) t := typ.common()
fl := flag(t.Kind()) fl := flag(t.Kind())
if ifaceIndir(t) { if ifaceIndir(t) {
return Value{t, unsafe_New(t), fl | flagIndir} return Value{t, unsafe_New(t), fl | flagIndir}
@ -105,11 +105,11 @@ func FirstMethodNameBytes(t Type) *byte {
panic("type has no methods") panic("type has no methods")
} }
m := ut.Methods()[0] m := ut.Methods()[0]
mname := t.(*rtype).nameOff(m.Name) mname := t.(rtype).nameOff(m.Name)
if *mname.data(0, "name flag field")&(1<<2) == 0 { if *mname.DataChecked(0, "name flag field")&(1<<2) == 0 {
panic("method name does not have pkgPath *string") panic("method name does not have pkgPath *string")
} }
return mname.bytes return mname.Bytes
} }
type Buffer struct { type Buffer struct {

View File

@ -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() size := typ.Size()
hasPtr := typ.PtrBytes != 0 hasPtr := typ.PtrBytes != 0

View File

@ -63,7 +63,7 @@ type Type interface {
// It panics if the type's Kind is not Ptr. // It panics if the type's Kind is not Ptr.
Elem() Type Elem() Type
common() *rtype common() *abi.Type
uncommon() *uncommonType uncommon() *uncommonType
} }
@ -92,7 +92,7 @@ type typeOff = abi.TypeOff
type textOff = abi.TextOff type textOff = abi.TextOff
type rtype struct { type rtype struct {
abi.Type *abi.Type
} }
// uncommonType is present only for defined types or types with methods // 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. // to describe a non-defined type with no methods.
type uncommonType = abi.UncommonType 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. // arrayType represents a fixed array type.
type arrayType = abi.ArrayType type arrayType = abi.ArrayType
// chanType represents a channel type. // chanType represents a channel type.
type chanType = abi.ChanType type chanType = abi.ChanType
// funcType represents a function type. type funcType = abi.FuncType
//
// 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 ...
}
// interfaceType represents an interface type. type interfaceType = abi.InterfaceType
type interfaceType struct {
rtype
pkgPath name // import path
methods []abi.Imethod // sorted by hash
}
// mapType represents a map type. // mapType represents a map type.
type mapType struct { type mapType struct {
rtype rtype
key *rtype // map key type Key *abi.Type // map key type
elem *rtype // map element (value) type Elem *abi.Type // map element (value) type
bucket *rtype // internal bucket structure Bucket *abi.Type // internal bucket structure
// function for hashing keys (ptr to key, seed) -> hash // function for hashing keys (ptr to key, seed) -> hash
hasher func(unsafe.Pointer, uintptr) uintptr Hasher func(unsafe.Pointer, uintptr) uintptr
keysize uint8 // size of key slot KeySize uint8 // size of key slot
valuesize uint8 // size of value slot ValueSize uint8 // size of value slot
bucketsize uint16 // size of bucket BucketSize uint16 // size of bucket
flags uint32 Flags uint32
} }
// ptrType represents a pointer type. // ptrType represents a pointer type.
type ptrType struct { type ptrType = abi.PtrType
rtype
elem *rtype // pointer element (pointed at) type
}
// sliceType represents a slice type. // sliceType represents a slice type.
type sliceType struct { type sliceType = abi.SliceType
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()
}
// structType represents a struct type. // structType represents a struct type.
type structType struct { type structType = abi.StructType
rtype
pkgPath name
fields []structField // sorted by offset
}
// name is an encoded type name with optional extra data. // 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) return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
} }
func (n name) pkgPath() string { func pkgPath(n abi.Name) string {
if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 { if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
return "" return ""
} }
i, l := n.readVarint(1) i, l := n.ReadVarint(1)
off := 1 + i + l off := 1 + i + l
if n.hasTag() { if n.HasTag() {
i2, l2 := n.readVarint(off) i2, l2 := n.ReadVarint(off)
off += i2 + l2 off += i2 + l2
} }
var nameOff int32 var nameOff int32
// Note that this field may not be aligned in memory, // Note that this field may not be aligned in memory,
// so we cannot use a direct int32 assignment here. // 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")))[:]) 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))} pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
return pkgPathName.name() return pkgPathName.name()
} }
@ -290,31 +240,29 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
// Implemented in the runtime package. // Implemented in the runtime package.
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
func (t *rtype) nameOff(off nameOff) name { func (t rtype) nameOff(off nameOff) abi.Name {
return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))} return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
} }
func (t *rtype) typeOff(off typeOff) *rtype { func (t rtype) typeOff(off typeOff) *abi.Type {
return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off))) return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
} }
func (t *rtype) uncommon() *uncommonType { func (t rtype) uncommon() *uncommonType {
return t.Uncommon() return t.Uncommon()
} }
func (t *rtype) String() string { func (t rtype) String() string {
s := t.nameOff(t.Str).name() s := t.nameOff(t.Str).Name()
if t.TFlag&abi.TFlagExtraStar != 0 { if t.TFlag&abi.TFlagExtraStar != 0 {
return s[1:] return s[1:]
} }
return s 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() ut := t.uncommon()
if ut == nil { if ut == nil {
return nil return nil
@ -322,15 +270,15 @@ func (t *rtype) exportedMethods() []abi.Method {
return ut.ExportedMethods() return ut.ExportedMethods()
} }
func (t *rtype) NumMethod() int { func (t rtype) NumMethod() int {
if t.Kind() == Interface { tt := t.Type.InterfaceType()
tt := (*interfaceType)(unsafe.Pointer(t)) if tt != nil {
return tt.NumMethod() return tt.NumMethod()
} }
return len(t.exportedMethods()) return len(t.exportedMethods())
} }
func (t *rtype) PkgPath() string { func (t rtype) PkgPath() string {
if t.TFlag&abi.TFlagNamed == 0 { if t.TFlag&abi.TFlagNamed == 0 {
return "" return ""
} }
@ -338,15 +286,11 @@ func (t *rtype) PkgPath() string {
if ut == nil { if ut == nil {
return "" return ""
} }
return t.nameOff(ut.PkgPath).name() return t.nameOff(ut.PkgPath).Name()
} }
func (t *rtype) hasName() bool { func (t rtype) Name() string {
return t.TFlag&abi.TFlagNamed != 0 if !t.HasName() {
}
func (t *rtype) Name() string {
if !t.hasName() {
return "" return ""
} }
s := t.String() s := t.String()
@ -364,116 +308,76 @@ func (t *rtype) Name() string {
return s[i+1:] return s[i+1:]
} }
func (t *rtype) chanDir() chanDir { func toRType(t *abi.Type) rtype {
if t.Kind() != abi.Chan { return rtype{t}
panic("reflect: chanDir of non-chan type") }
func elem(t *abi.Type) *abi.Type {
et := t.Elem()
if et != nil {
return et
} }
tt := (*chanType)(unsafe.Pointer(t)) panic("reflect: Elem of invalid type " + toRType(t).String())
return chanDir(tt.Dir)
} }
func toRType(t *abi.Type) *rtype { func (t rtype) Elem() Type {
return (*rtype)(unsafe.Pointer(t)) return toType(elem(t.common()))
} }
func (t *rtype) Elem() Type { func (t rtype) In(i int) Type {
switch t.Kind() { tt := t.Type.FuncType()
case abi.Array: if tt == nil {
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 {
panic("reflect: In of non-func type") panic("reflect: In of non-func type")
} }
tt := (*funcType)(unsafe.Pointer(t)) return toType(tt.InSlice()[i])
return toType(tt.in()[i])
} }
func (t *rtype) Key() Type { func (t rtype) Key() Type {
if t.Kind() != abi.Map { tt := t.Type.MapType()
if tt == nil {
panic("reflect: Key of non-map type") 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 { func (t rtype) Len() int {
if t.Kind() != abi.Array { tt := t.Type.ArrayType()
if tt == nil {
panic("reflect: Len of non-array type") panic("reflect: Len of non-array type")
} }
tt := (*arrayType)(unsafe.Pointer(t))
return int(tt.Len) return int(tt.Len)
} }
func (t *rtype) NumField() int { func (t rtype) NumField() int {
if t.Kind() != abi.Struct { tt := t.Type.StructType()
if tt == nil {
panic("reflect: NumField of non-struct type") 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 { func (t rtype) NumIn() int {
if t.Kind() != abi.Func { tt := t.Type.FuncType()
if tt == nil {
panic("reflect: NumIn of non-func type") 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 { func (t rtype) NumOut() int {
if t.Kind() != abi.Func { tt := t.Type.FuncType()
if tt == nil {
panic("reflect: NumOut of non-func type") panic("reflect: NumOut of non-func type")
} }
tt := (*funcType)(unsafe.Pointer(t)) return tt.NumOut()
return len(tt.out())
} }
func (t *rtype) Out(i int) Type { func (t rtype) Out(i int) Type {
if t.Kind() != abi.Func { tt := t.Type.FuncType()
if tt == nil {
panic("reflect: Out of non-func type") panic("reflect: Out of non-func type")
} }
tt := (*funcType)(unsafe.Pointer(t)) return toType(tt.OutSlice()[i])
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]
} }
// add returns p+x. // 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) 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. // TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil. // If i is a nil interface value, TypeOf returns nil.
func TypeOf(i any) Type { func TypeOf(i any) Type {
@ -497,37 +398,40 @@ func TypeOf(i any) Type {
return toType(eface.typ) return toType(eface.typ)
} }
func (t *rtype) Implements(u Type) bool { func (t rtype) Implements(u Type) bool {
if u == nil { if u == nil {
panic("reflect: nil type passed to Type.Implements") panic("reflect: nil type passed to Type.Implements")
} }
if u.Kind() != Interface { if u.Kind() != Interface {
panic("reflect: non-interface type passed to Type.Implements") 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 { if u == nil {
panic("reflect: nil type passed to Type.AssignableTo") panic("reflect: nil type passed to Type.AssignableTo")
} }
uu := u.(*rtype) uu := u.common()
return directlyAssignable(uu, t) || implements(uu, t) tt := t.common()
return directlyAssignable(uu, tt) || implements(uu, tt)
} }
func (t *rtype) Comparable() bool { func (t rtype) Comparable() bool {
return t.Equal != nil return t.Equal != nil
} }
// implements reports whether the type V implements the interface type T. // implements reports whether the type V implements the interface type T.
func implements(T, V *rtype) bool { func implements(T, V *abi.Type) bool {
if T.Kind() != Interface { t := T.InterfaceType()
if t == nil {
return false return false
} }
t := (*interfaceType)(unsafe.Pointer(T)) if len(t.Methods) == 0 {
if len(t.methods) == 0 {
return true return true
} }
rT := toRType(T)
rV := toRType(V)
// The same algorithm applies in both cases, but the // The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type // method tables for an interface type and a concrete type
@ -544,26 +448,26 @@ func implements(T, V *rtype) bool {
if V.Kind() == Interface { if V.Kind() == Interface {
v := (*interfaceType)(unsafe.Pointer(V)) v := (*interfaceType)(unsafe.Pointer(V))
i := 0 i := 0
for j := 0; j < len(v.methods); j++ { for j := 0; j < len(v.Methods); j++ {
tm := &t.methods[i] tm := &t.Methods[i]
tmName := t.nameOff(tm.Name) tmName := rT.nameOff(tm.Name)
vm := &v.methods[j] vm := &v.Methods[j]
vmName := V.nameOff(vm.Name) vmName := rV.nameOff(vm.Name)
if vmName.name() == tmName.name() && V.typeOff(vm.Typ) == t.typeOff(tm.Typ) { if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
if !tmName.isExported() { if !tmName.IsExported() {
tmPkgPath := tmName.pkgPath() tmPkgPath := pkgPath(tmName)
if tmPkgPath == "" { if tmPkgPath == "" {
tmPkgPath = t.pkgPath.name() tmPkgPath = t.PkgPath.Name()
} }
vmPkgPath := vmName.pkgPath() vmPkgPath := pkgPath(vmName)
if vmPkgPath == "" { if vmPkgPath == "" {
vmPkgPath = v.pkgPath.name() vmPkgPath = v.PkgPath.Name()
} }
if tmPkgPath != vmPkgPath { if tmPkgPath != vmPkgPath {
continue continue
} }
} }
if i++; i >= len(t.methods) { if i++; i >= len(t.Methods) {
return true return true
} }
} }
@ -571,32 +475,32 @@ func implements(T, V *rtype) bool {
return false return false
} }
v := V.uncommon() v := V.Uncommon()
if v == nil { if v == nil {
return false return false
} }
i := 0 i := 0
vmethods := v.Methods() vmethods := v.Methods()
for j := 0; j < int(v.Mcount); j++ { for j := 0; j < int(v.Mcount); j++ {
tm := &t.methods[i] tm := &t.Methods[i]
tmName := t.nameOff(tm.Name) tmName := rT.nameOff(tm.Name)
vm := vmethods[j] vm := vmethods[j]
vmName := V.nameOff(vm.Name) vmName := rV.nameOff(vm.Name)
if vmName.name() == tmName.name() && V.typeOff(vm.Mtyp) == t.typeOff(tm.Typ) { if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
if !tmName.isExported() { if !tmName.IsExported() {
tmPkgPath := tmName.pkgPath() tmPkgPath := pkgPath(tmName)
if tmPkgPath == "" { if tmPkgPath == "" {
tmPkgPath = t.pkgPath.name() tmPkgPath = t.PkgPath.Name()
} }
vmPkgPath := vmName.pkgPath() vmPkgPath := pkgPath(vmName)
if vmPkgPath == "" { if vmPkgPath == "" {
vmPkgPath = V.nameOff(v.PkgPath).name() vmPkgPath = rV.nameOff(v.PkgPath).Name()
} }
if tmPkgPath != vmPkgPath { if tmPkgPath != vmPkgPath {
continue continue
} }
} }
if i++; i >= len(t.methods) { if i++; i >= len(t.Methods) {
return true return true
} }
} }
@ -609,7 +513,7 @@ func implements(T, V *rtype) bool {
// https://golang.org/doc/go_spec.html#Assignability // https://golang.org/doc/go_spec.html#Assignability
// Ignoring the interface rules (implemented elsewhere) // Ignoring the interface rules (implemented elsewhere)
// and the ideal constant rules (no ideal constants at run time). // 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? // x's type V is identical to T?
if T == V { if T == V {
return true return true
@ -617,7 +521,7 @@ func directlyAssignable(T, V *rtype) bool {
// Otherwise at least one of T and V must not be defined // Otherwise at least one of T and V must not be defined
// and they must have the same kind. // 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 return false
} }
@ -625,19 +529,19 @@ func directlyAssignable(T, V *rtype) bool {
return haveIdenticalUnderlyingType(T, V, true) return haveIdenticalUnderlyingType(T, V, true)
} }
func haveIdenticalType(T, V Type, cmpTags bool) bool { func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
if cmpTags { if cmpTags {
return T == V 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 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 { if T == V {
return true return true
} }
@ -662,17 +566,17 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
// Special case: // Special case:
// x is a bidirectional channel value, T is a channel type, // x is a bidirectional channel value, T is a channel type,
// and x's type V and T have identical element types. // 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 return true
} }
// Otherwise continue test for identical underlying type. // 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: case abi.Func:
t := (*funcType)(unsafe.Pointer(T)) t := (*funcType)(unsafe.Pointer(T))
v := (*funcType)(unsafe.Pointer(V)) 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 return false
} }
for i := 0; i < t.NumIn(); i++ { for i := 0; i < t.NumIn(); i++ {
@ -690,7 +594,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
case Interface: case Interface:
t := (*interfaceType)(unsafe.Pointer(T)) t := (*interfaceType)(unsafe.Pointer(T))
v := (*interfaceType)(unsafe.Pointer(V)) 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 return true
} }
// Might have the same methods but still // Might have the same methods but still
@ -706,28 +610,28 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
case abi.Struct: case abi.Struct:
t := (*structType)(unsafe.Pointer(T)) t := (*structType)(unsafe.Pointer(T))
v := (*structType)(unsafe.Pointer(V)) v := (*structType)(unsafe.Pointer(V))
if len(t.fields) != len(v.fields) { if len(t.Fields) != len(v.Fields) {
return false return false
} }
if t.pkgPath.name() != v.pkgPath.name() { if t.PkgPath.Name() != v.PkgPath.Name() {
return false return false
} }
for i := range t.fields { for i := range t.Fields {
tf := &t.fields[i] tf := &t.Fields[i]
vf := &v.fields[i] vf := &v.Fields[i]
if tf.name.name() != vf.name.name() { if tf.Name.Name() != vf.Name.Name() {
return false return false
} }
if !haveIdenticalType(tf.typ, vf.typ, cmpTags) { if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
return false return false
} }
if cmpTags && tf.name.tag() != vf.name.tag() { if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
return false return false
} }
if tf.offset != vf.offset { if tf.Offset != vf.Offset {
return false return false
} }
if tf.embedded() != vf.embedded() { if tf.Embedded() != vf.Embedded() {
return false return false
} }
} }
@ -737,24 +641,19 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
return false return false
} }
type structTypeUncommon struct {
structType
u uncommonType
}
// toType converts from a *rtype to a Type that can be returned // 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 // 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 // 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 // function takes care of ensuring that multiple *rtype for the same
// type are coalesced into a single Type. // type are coalesced into a single Type.
func toType(t *rtype) Type { func toType(t *abi.Type) Type {
if t == nil { if t == nil {
return nil return nil
} }
return t return toRType(t)
} }
// ifaceIndir reports whether t is stored indirectly in an interface value. // 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 return t.Kind_&abi.KindDirectIface == 0
} }

View File

@ -35,7 +35,7 @@ import (
// they represent. // they represent.
type Value struct { type Value struct {
// typ holds the type of the value represented by a Value. // 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. // Pointer-valued data or, if flagIndir is set, pointer to data.
// Valid when either flagIndir is set or typ.pointers() is true. // 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. // pointer returns the underlying pointer represented by v.
// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer // v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
func (v Value) pointer() unsafe.Pointer { 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") panic("can't call pointer on a non-pointer Value")
} }
if v.flag&flagIndir != 0 { if v.flag&flagIndir != 0 {
@ -179,7 +179,7 @@ func methodName() string {
// emptyInterface is the header for an interface{} value. // emptyInterface is the header for an interface{} value.
type emptyInterface struct { type emptyInterface struct {
typ *rtype typ *abi.Type
word unsafe.Pointer word unsafe.Pointer
} }
@ -250,7 +250,7 @@ func (v Value) Elem() Value {
return Value{} return Value{}
} }
tt := (*ptrType)(unsafe.Pointer(v.typ)) tt := (*ptrType)(unsafe.Pointer(v.typ))
typ := tt.elem typ := tt.Elem
fl := v.flag&flagRO | flagIndir | flagAddr fl := v.flag&flagRO | flagIndir | flagAddr
fl |= flag(typ.Kind()) fl |= flag(typ.Kind())
return Value{typ, ptr, fl} return Value{typ, ptr, fl}
@ -380,7 +380,7 @@ func (v Value) Type() Type {
panic(&ValueError{"reflectlite.Value.Type", abi.Invalid}) panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
} }
// Method values not supported. // Method values not supported.
return v.typ return toRType(v.typ)
} }
/* /*
@ -388,7 +388,7 @@ func (v Value) Type() Type {
*/ */
// implemented in package runtime // 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 // ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero 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. // assignTo returns a value v that can be assigned directly to typ.
// It panics if v is not assignable 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. // 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 { // if v.flag&flagMethod != 0 {
// v = makeMethodValue(context, v) // v = makeMethodValue(context, v)
// } // }
@ -442,7 +442,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
} }
// Failed. // 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, // 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") 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. // typedmemmove copies a value of type t to dst from src.
// //
//go:noescape //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, // Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that // for use in cases where the reflect code is so clever that