// It panics if the type's Kind is not Ptr.
Elem() Type
- common() *rtype
+ common() *abi.Type
uncommon() *uncommonType
}
type textOff = abi.TextOff
type rtype struct {
- abi.Type
+ *abi.Type
}
// uncommonType is present only for defined types or types with methods
// 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.
//
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()
}
// 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() *rtype { return t }
+func (t rtype) common() *abi.Type { return t.Type }
-func (t *rtype) exportedMethods() []abi.Method {
+func (t rtype) exportedMethods() []abi.Method {
ut := t.uncommon()
if ut == nil {
return nil
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 ""
}
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()
return s[i+1:]
}
-func (t *rtype) chanDir() chanDir {
- if t.Kind() != abi.Chan {
- panic("reflect: chanDir of non-chan type")
- }
- tt := (*chanType)(unsafe.Pointer(t))
- return chanDir(tt.Dir)
+func toRType(t *abi.Type) rtype {
+ return rtype{t}
}
-func toRType(t *abi.Type) *rtype {
- return (*rtype)(unsafe.Pointer(t))
+func elem(t *abi.Type) *abi.Type {
+ et := t.Elem()
+ if et != nil {
+ return et
+ }
+ panic("reflect: Elem of invalid type " + toRType(t).String())
}
-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) Elem() Type {
+ return toType(elem(t.common()))
}
-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.
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 {
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
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
}
}
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
}
}
// 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
// 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
}
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
}
// 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++ {
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
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
}
}
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
}