Source file src/internal/reflectlite/type.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package reflectlite implements lightweight version of reflect, not using
     6  // any package except for "runtime" and "unsafe".
     7  package reflectlite
     8  
     9  import (
    10  	"internal/unsafeheader"
    11  	"unsafe"
    12  )
    13  
    14  // Type is the representation of a Go type.
    15  //
    16  // Not all methods apply to all kinds of types. Restrictions,
    17  // if any, are noted in the documentation for each method.
    18  // Use the Kind method to find out the kind of type before
    19  // calling kind-specific methods. Calling a method
    20  // inappropriate to the kind of type causes a run-time panic.
    21  //
    22  // Type values are comparable, such as with the == operator,
    23  // so they can be used as map keys.
    24  // Two Type values are equal if they represent identical types.
    25  type Type interface {
    26  	// Methods applicable to all types.
    27  
    28  	// Name returns the type's name within its package for a defined type.
    29  	// For other (non-defined) types it returns the empty string.
    30  	Name() string
    31  
    32  	// PkgPath returns a defined type's package path, that is, the import path
    33  	// that uniquely identifies the package, such as "encoding/base64".
    34  	// If the type was predeclared (string, error) or not defined (*T, struct{},
    35  	// []int, or A where A is an alias for a non-defined type), the package path
    36  	// will be the empty string.
    37  	PkgPath() string
    38  
    39  	// Size returns the number of bytes needed to store
    40  	// a value of the given type; it is analogous to unsafe.Sizeof.
    41  	Size() uintptr
    42  
    43  	// Kind returns the specific kind of this type.
    44  	Kind() Kind
    45  
    46  	// Implements reports whether the type implements the interface type u.
    47  	Implements(u Type) bool
    48  
    49  	// AssignableTo reports whether a value of the type is assignable to type u.
    50  	AssignableTo(u Type) bool
    51  
    52  	// Comparable reports whether values of this type are comparable.
    53  	Comparable() bool
    54  
    55  	// String returns a string representation of the type.
    56  	// The string representation may use shortened package names
    57  	// (e.g., base64 instead of "encoding/base64") and is not
    58  	// guaranteed to be unique among types. To test for type identity,
    59  	// compare the Types directly.
    60  	String() string
    61  
    62  	// Elem returns a type's element type.
    63  	// It panics if the type's Kind is not Ptr.
    64  	Elem() Type
    65  
    66  	common() *rtype
    67  	uncommon() *uncommonType
    68  }
    69  
    70  /*
    71   * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
    72   * A few are known to ../runtime/type.go to convey to debuggers.
    73   * They are also known to ../runtime/type.go.
    74   */
    75  
    76  // A Kind represents the specific kind of type that a Type represents.
    77  // The zero Kind is not a valid kind.
    78  type Kind uint
    79  
    80  const (
    81  	Invalid Kind = iota
    82  	Bool
    83  	Int
    84  	Int8
    85  	Int16
    86  	Int32
    87  	Int64
    88  	Uint
    89  	Uint8
    90  	Uint16
    91  	Uint32
    92  	Uint64
    93  	Uintptr
    94  	Float32
    95  	Float64
    96  	Complex64
    97  	Complex128
    98  	Array
    99  	Chan
   100  	Func
   101  	Interface
   102  	Map
   103  	Pointer
   104  	Slice
   105  	String
   106  	Struct
   107  	UnsafePointer
   108  )
   109  
   110  const Ptr = Pointer
   111  
   112  // tflag is used by an rtype to signal what extra type information is
   113  // available in the memory directly following the rtype value.
   114  //
   115  // tflag values must be kept in sync with copies in:
   116  //	cmd/compile/internal/reflectdata/reflect.go
   117  //	cmd/link/internal/ld/decodesym.go
   118  //	runtime/type.go
   119  type tflag uint8
   120  
   121  const (
   122  	// tflagUncommon means that there is a pointer, *uncommonType,
   123  	// just beyond the outer type structure.
   124  	//
   125  	// For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0,
   126  	// then t has uncommonType data and it can be accessed as:
   127  	//
   128  	//	type tUncommon struct {
   129  	//		structType
   130  	//		u uncommonType
   131  	//	}
   132  	//	u := &(*tUncommon)(unsafe.Pointer(t)).u
   133  	tflagUncommon tflag = 1 << 0
   134  
   135  	// tflagExtraStar means the name in the str field has an
   136  	// extraneous '*' prefix. This is because for most types T in
   137  	// a program, the type *T also exists and reusing the str data
   138  	// saves binary size.
   139  	tflagExtraStar tflag = 1 << 1
   140  
   141  	// tflagNamed means the type has a name.
   142  	tflagNamed tflag = 1 << 2
   143  
   144  	// tflagRegularMemory means that equal and hash functions can treat
   145  	// this type as a single region of t.size bytes.
   146  	tflagRegularMemory tflag = 1 << 3
   147  )
   148  
   149  // rtype is the common implementation of most values.
   150  // It is embedded in other struct types.
   151  //
   152  // rtype must be kept in sync with ../runtime/type.go:/^type._type.
   153  type rtype struct {
   154  	size       uintptr
   155  	ptrdata    uintptr // number of bytes in the type that can contain pointers
   156  	hash       uint32  // hash of type; avoids computation in hash tables
   157  	tflag      tflag   // extra type information flags
   158  	align      uint8   // alignment of variable with this type
   159  	fieldAlign uint8   // alignment of struct field with this type
   160  	kind       uint8   // enumeration for C
   161  	// function for comparing objects of this type
   162  	// (ptr to object A, ptr to object B) -> ==?
   163  	equal     func(unsafe.Pointer, unsafe.Pointer) bool
   164  	gcdata    *byte   // garbage collection data
   165  	str       nameOff // string form
   166  	ptrToThis typeOff // type for pointer to this type, may be zero
   167  }
   168  
   169  // Method on non-interface type
   170  type method struct {
   171  	name nameOff // name of method
   172  	mtyp typeOff // method type (without receiver)
   173  	ifn  textOff // fn used in interface call (one-word receiver)
   174  	tfn  textOff // fn used for normal method call
   175  }
   176  
   177  // uncommonType is present only for defined types or types with methods
   178  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   179  // Using a pointer to this struct reduces the overall size required
   180  // to describe a non-defined type with no methods.
   181  type uncommonType struct {
   182  	pkgPath nameOff // import path; empty for built-in types like int, string
   183  	mcount  uint16  // number of methods
   184  	xcount  uint16  // number of exported methods
   185  	moff    uint32  // offset from this uncommontype to [mcount]method
   186  	_       uint32  // unused
   187  }
   188  
   189  // chanDir represents a channel type's direction.
   190  type chanDir int
   191  
   192  const (
   193  	recvDir chanDir             = 1 << iota // <-chan
   194  	sendDir                                 // chan<-
   195  	bothDir = recvDir | sendDir             // chan
   196  )
   197  
   198  // arrayType represents a fixed array type.
   199  type arrayType struct {
   200  	rtype
   201  	elem  *rtype // array element type
   202  	slice *rtype // slice type
   203  	len   uintptr
   204  }
   205  
   206  // chanType represents a channel type.
   207  type chanType struct {
   208  	rtype
   209  	elem *rtype  // channel element type
   210  	dir  uintptr // channel direction (chanDir)
   211  }
   212  
   213  // funcType represents a function type.
   214  //
   215  // A *rtype for each in and out parameter is stored in an array that
   216  // directly follows the funcType (and possibly its uncommonType). So
   217  // a function type with one method, one input, and one output is:
   218  //
   219  //	struct {
   220  //		funcType
   221  //		uncommonType
   222  //		[2]*rtype    // [0] is in, [1] is out
   223  //	}
   224  type funcType struct {
   225  	rtype
   226  	inCount  uint16
   227  	outCount uint16 // top bit is set if last input parameter is ...
   228  }
   229  
   230  // imethod represents a method on an interface type
   231  type imethod struct {
   232  	name nameOff // name of method
   233  	typ  typeOff // .(*FuncType) underneath
   234  }
   235  
   236  // interfaceType represents an interface type.
   237  type interfaceType struct {
   238  	rtype
   239  	pkgPath name      // import path
   240  	methods []imethod // sorted by hash
   241  }
   242  
   243  // mapType represents a map type.
   244  type mapType struct {
   245  	rtype
   246  	key    *rtype // map key type
   247  	elem   *rtype // map element (value) type
   248  	bucket *rtype // internal bucket structure
   249  	// function for hashing keys (ptr to key, seed) -> hash
   250  	hasher     func(unsafe.Pointer, uintptr) uintptr
   251  	keysize    uint8  // size of key slot
   252  	valuesize  uint8  // size of value slot
   253  	bucketsize uint16 // size of bucket
   254  	flags      uint32
   255  }
   256  
   257  // ptrType represents a pointer type.
   258  type ptrType struct {
   259  	rtype
   260  	elem *rtype // pointer element (pointed at) type
   261  }
   262  
   263  // sliceType represents a slice type.
   264  type sliceType struct {
   265  	rtype
   266  	elem *rtype // slice element type
   267  }
   268  
   269  // Struct field
   270  type structField struct {
   271  	name        name    // name is always non-empty
   272  	typ         *rtype  // type of field
   273  	offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
   274  }
   275  
   276  func (f *structField) offset() uintptr {
   277  	return f.offsetEmbed >> 1
   278  }
   279  
   280  func (f *structField) embedded() bool {
   281  	return f.offsetEmbed&1 != 0
   282  }
   283  
   284  // structType represents a struct type.
   285  type structType struct {
   286  	rtype
   287  	pkgPath name
   288  	fields  []structField // sorted by offset
   289  }
   290  
   291  // name is an encoded type name with optional extra data.
   292  //
   293  // The first byte is a bit field containing:
   294  //
   295  //	1<<0 the name is exported
   296  //	1<<1 tag data follows the name
   297  //	1<<2 pkgPath nameOff follows the name and tag
   298  //
   299  // The next two bytes are the data length:
   300  //
   301  //	 l := uint16(data[1])<<8 | uint16(data[2])
   302  //
   303  // Bytes [3:3+l] are the string data.
   304  //
   305  // If tag data follows then bytes 3+l and 3+l+1 are the tag length,
   306  // with the data following.
   307  //
   308  // If the import path follows, then 4 bytes at the end of
   309  // the data form a nameOff. The import path is only set for concrete
   310  // methods that are defined in a different package than their type.
   311  //
   312  // If a name starts with "*", then the exported bit represents
   313  // whether the pointed to type is exported.
   314  type name struct {
   315  	bytes *byte
   316  }
   317  
   318  func (n name) data(off int, whySafe string) *byte {
   319  	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
   320  }
   321  
   322  func (n name) isExported() bool {
   323  	return (*n.bytes)&(1<<0) != 0
   324  }
   325  
   326  func (n name) hasTag() bool {
   327  	return (*n.bytes)&(1<<1) != 0
   328  }
   329  
   330  // readVarint parses a varint as encoded by encoding/binary.
   331  // It returns the number of encoded bytes and the encoded value.
   332  func (n name) readVarint(off int) (int, int) {
   333  	v := 0
   334  	for i := 0; ; i++ {
   335  		x := *n.data(off+i, "read varint")
   336  		v += int(x&0x7f) << (7 * i)
   337  		if x&0x80 == 0 {
   338  			return i + 1, v
   339  		}
   340  	}
   341  }
   342  
   343  func (n name) name() (s string) {
   344  	if n.bytes == nil {
   345  		return
   346  	}
   347  	i, l := n.readVarint(1)
   348  	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
   349  	hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string"))
   350  	hdr.Len = l
   351  	return
   352  }
   353  
   354  func (n name) tag() (s string) {
   355  	if !n.hasTag() {
   356  		return ""
   357  	}
   358  	i, l := n.readVarint(1)
   359  	i2, l2 := n.readVarint(1 + i + l)
   360  	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
   361  	hdr.Data = unsafe.Pointer(n.data(1+i+l+i2, "non-empty string"))
   362  	hdr.Len = l2
   363  	return
   364  }
   365  
   366  func (n name) pkgPath() string {
   367  	if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
   368  		return ""
   369  	}
   370  	i, l := n.readVarint(1)
   371  	off := 1 + i + l
   372  	if n.hasTag() {
   373  		i2, l2 := n.readVarint(off)
   374  		off += i2 + l2
   375  	}
   376  	var nameOff int32
   377  	// Note that this field may not be aligned in memory,
   378  	// so we cannot use a direct int32 assignment here.
   379  	copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
   380  	pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
   381  	return pkgPathName.name()
   382  }
   383  
   384  /*
   385   * The compiler knows the exact layout of all the data structures above.
   386   * The compiler does not know about the data structures and methods below.
   387   */
   388  
   389  const (
   390  	kindDirectIface = 1 << 5
   391  	kindGCProg      = 1 << 6 // Type.gc points to GC program
   392  	kindMask        = (1 << 5) - 1
   393  )
   394  
   395  // String returns the name of k.
   396  func (k Kind) String() string {
   397  	if int(k) < len(kindNames) {
   398  		return kindNames[k]
   399  	}
   400  	return kindNames[0]
   401  }
   402  
   403  var kindNames = []string{
   404  	Invalid:       "invalid",
   405  	Bool:          "bool",
   406  	Int:           "int",
   407  	Int8:          "int8",
   408  	Int16:         "int16",
   409  	Int32:         "int32",
   410  	Int64:         "int64",
   411  	Uint:          "uint",
   412  	Uint8:         "uint8",
   413  	Uint16:        "uint16",
   414  	Uint32:        "uint32",
   415  	Uint64:        "uint64",
   416  	Uintptr:       "uintptr",
   417  	Float32:       "float32",
   418  	Float64:       "float64",
   419  	Complex64:     "complex64",
   420  	Complex128:    "complex128",
   421  	Array:         "array",
   422  	Chan:          "chan",
   423  	Func:          "func",
   424  	Interface:     "interface",
   425  	Map:           "map",
   426  	Ptr:           "ptr",
   427  	Slice:         "slice",
   428  	String:        "string",
   429  	Struct:        "struct",
   430  	UnsafePointer: "unsafe.Pointer",
   431  }
   432  
   433  func (t *uncommonType) methods() []method {
   434  	if t.mcount == 0 {
   435  		return nil
   436  	}
   437  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
   438  }
   439  
   440  func (t *uncommonType) exportedMethods() []method {
   441  	if t.xcount == 0 {
   442  		return nil
   443  	}
   444  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
   445  }
   446  
   447  // resolveNameOff resolves a name offset from a base pointer.
   448  // The (*rtype).nameOff method is a convenience wrapper for this function.
   449  // Implemented in the runtime package.
   450  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
   451  
   452  // resolveTypeOff resolves an *rtype offset from a base type.
   453  // The (*rtype).typeOff method is a convenience wrapper for this function.
   454  // Implemented in the runtime package.
   455  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   456  
   457  type nameOff int32 // offset to a name
   458  type typeOff int32 // offset to an *rtype
   459  type textOff int32 // offset from top of text section
   460  
   461  func (t *rtype) nameOff(off nameOff) name {
   462  	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
   463  }
   464  
   465  func (t *rtype) typeOff(off typeOff) *rtype {
   466  	return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
   467  }
   468  
   469  func (t *rtype) uncommon() *uncommonType {
   470  	if t.tflag&tflagUncommon == 0 {
   471  		return nil
   472  	}
   473  	switch t.Kind() {
   474  	case Struct:
   475  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   476  	case Ptr:
   477  		type u struct {
   478  			ptrType
   479  			u uncommonType
   480  		}
   481  		return &(*u)(unsafe.Pointer(t)).u
   482  	case Func:
   483  		type u struct {
   484  			funcType
   485  			u uncommonType
   486  		}
   487  		return &(*u)(unsafe.Pointer(t)).u
   488  	case Slice:
   489  		type u struct {
   490  			sliceType
   491  			u uncommonType
   492  		}
   493  		return &(*u)(unsafe.Pointer(t)).u
   494  	case Array:
   495  		type u struct {
   496  			arrayType
   497  			u uncommonType
   498  		}
   499  		return &(*u)(unsafe.Pointer(t)).u
   500  	case Chan:
   501  		type u struct {
   502  			chanType
   503  			u uncommonType
   504  		}
   505  		return &(*u)(unsafe.Pointer(t)).u
   506  	case Map:
   507  		type u struct {
   508  			mapType
   509  			u uncommonType
   510  		}
   511  		return &(*u)(unsafe.Pointer(t)).u
   512  	case Interface:
   513  		type u struct {
   514  			interfaceType
   515  			u uncommonType
   516  		}
   517  		return &(*u)(unsafe.Pointer(t)).u
   518  	default:
   519  		type u struct {
   520  			rtype
   521  			u uncommonType
   522  		}
   523  		return &(*u)(unsafe.Pointer(t)).u
   524  	}
   525  }
   526  
   527  func (t *rtype) String() string {
   528  	s := t.nameOff(t.str).name()
   529  	if t.tflag&tflagExtraStar != 0 {
   530  		return s[1:]
   531  	}
   532  	return s
   533  }
   534  
   535  func (t *rtype) Size() uintptr { return t.size }
   536  
   537  func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
   538  
   539  func (t *rtype) pointers() bool { return t.ptrdata != 0 }
   540  
   541  func (t *rtype) common() *rtype { return t }
   542  
   543  func (t *rtype) exportedMethods() []method {
   544  	ut := t.uncommon()
   545  	if ut == nil {
   546  		return nil
   547  	}
   548  	return ut.exportedMethods()
   549  }
   550  
   551  func (t *rtype) NumMethod() int {
   552  	if t.Kind() == Interface {
   553  		tt := (*interfaceType)(unsafe.Pointer(t))
   554  		return tt.NumMethod()
   555  	}
   556  	return len(t.exportedMethods())
   557  }
   558  
   559  func (t *rtype) PkgPath() string {
   560  	if t.tflag&tflagNamed == 0 {
   561  		return ""
   562  	}
   563  	ut := t.uncommon()
   564  	if ut == nil {
   565  		return ""
   566  	}
   567  	return t.nameOff(ut.pkgPath).name()
   568  }
   569  
   570  func (t *rtype) hasName() bool {
   571  	return t.tflag&tflagNamed != 0
   572  }
   573  
   574  func (t *rtype) Name() string {
   575  	if !t.hasName() {
   576  		return ""
   577  	}
   578  	s := t.String()
   579  	i := len(s) - 1
   580  	for i >= 0 && s[i] != '.' {
   581  		i--
   582  	}
   583  	return s[i+1:]
   584  }
   585  
   586  func (t *rtype) chanDir() chanDir {
   587  	if t.Kind() != Chan {
   588  		panic("reflect: chanDir of non-chan type")
   589  	}
   590  	tt := (*chanType)(unsafe.Pointer(t))
   591  	return chanDir(tt.dir)
   592  }
   593  
   594  func (t *rtype) Elem() Type {
   595  	switch t.Kind() {
   596  	case Array:
   597  		tt := (*arrayType)(unsafe.Pointer(t))
   598  		return toType(tt.elem)
   599  	case Chan:
   600  		tt := (*chanType)(unsafe.Pointer(t))
   601  		return toType(tt.elem)
   602  	case Map:
   603  		tt := (*mapType)(unsafe.Pointer(t))
   604  		return toType(tt.elem)
   605  	case Ptr:
   606  		tt := (*ptrType)(unsafe.Pointer(t))
   607  		return toType(tt.elem)
   608  	case Slice:
   609  		tt := (*sliceType)(unsafe.Pointer(t))
   610  		return toType(tt.elem)
   611  	}
   612  	panic("reflect: Elem of invalid type")
   613  }
   614  
   615  func (t *rtype) In(i int) Type {
   616  	if t.Kind() != Func {
   617  		panic("reflect: In of non-func type")
   618  	}
   619  	tt := (*funcType)(unsafe.Pointer(t))
   620  	return toType(tt.in()[i])
   621  }
   622  
   623  func (t *rtype) Key() Type {
   624  	if t.Kind() != Map {
   625  		panic("reflect: Key of non-map type")
   626  	}
   627  	tt := (*mapType)(unsafe.Pointer(t))
   628  	return toType(tt.key)
   629  }
   630  
   631  func (t *rtype) Len() int {
   632  	if t.Kind() != Array {
   633  		panic("reflect: Len of non-array type")
   634  	}
   635  	tt := (*arrayType)(unsafe.Pointer(t))
   636  	return int(tt.len)
   637  }
   638  
   639  func (t *rtype) NumField() int {
   640  	if t.Kind() != Struct {
   641  		panic("reflect: NumField of non-struct type")
   642  	}
   643  	tt := (*structType)(unsafe.Pointer(t))
   644  	return len(tt.fields)
   645  }
   646  
   647  func (t *rtype) NumIn() int {
   648  	if t.Kind() != Func {
   649  		panic("reflect: NumIn of non-func type")
   650  	}
   651  	tt := (*funcType)(unsafe.Pointer(t))
   652  	return int(tt.inCount)
   653  }
   654  
   655  func (t *rtype) NumOut() int {
   656  	if t.Kind() != Func {
   657  		panic("reflect: NumOut of non-func type")
   658  	}
   659  	tt := (*funcType)(unsafe.Pointer(t))
   660  	return len(tt.out())
   661  }
   662  
   663  func (t *rtype) Out(i int) Type {
   664  	if t.Kind() != Func {
   665  		panic("reflect: Out of non-func type")
   666  	}
   667  	tt := (*funcType)(unsafe.Pointer(t))
   668  	return toType(tt.out()[i])
   669  }
   670  
   671  func (t *funcType) in() []*rtype {
   672  	uadd := unsafe.Sizeof(*t)
   673  	if t.tflag&tflagUncommon != 0 {
   674  		uadd += unsafe.Sizeof(uncommonType{})
   675  	}
   676  	if t.inCount == 0 {
   677  		return nil
   678  	}
   679  	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
   680  }
   681  
   682  func (t *funcType) out() []*rtype {
   683  	uadd := unsafe.Sizeof(*t)
   684  	if t.tflag&tflagUncommon != 0 {
   685  		uadd += unsafe.Sizeof(uncommonType{})
   686  	}
   687  	outCount := t.outCount & (1<<15 - 1)
   688  	if outCount == 0 {
   689  		return nil
   690  	}
   691  	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
   692  }
   693  
   694  // add returns p+x.
   695  //
   696  // The whySafe string is ignored, so that the function still inlines
   697  // as efficiently as p+x, but all call sites should use the string to
   698  // record why the addition is safe, which is to say why the addition
   699  // does not cause x to advance to the very end of p's allocation
   700  // and therefore point incorrectly at the next block in memory.
   701  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   702  	return unsafe.Pointer(uintptr(p) + x)
   703  }
   704  
   705  // NumMethod returns the number of interface methods in the type's method set.
   706  func (t *interfaceType) NumMethod() int { return len(t.methods) }
   707  
   708  // TypeOf returns the reflection Type that represents the dynamic type of i.
   709  // If i is a nil interface value, TypeOf returns nil.
   710  func TypeOf(i any) Type {
   711  	eface := *(*emptyInterface)(unsafe.Pointer(&i))
   712  	return toType(eface.typ)
   713  }
   714  
   715  func (t *rtype) Implements(u Type) bool {
   716  	if u == nil {
   717  		panic("reflect: nil type passed to Type.Implements")
   718  	}
   719  	if u.Kind() != Interface {
   720  		panic("reflect: non-interface type passed to Type.Implements")
   721  	}
   722  	return implements(u.(*rtype), t)
   723  }
   724  
   725  func (t *rtype) AssignableTo(u Type) bool {
   726  	if u == nil {
   727  		panic("reflect: nil type passed to Type.AssignableTo")
   728  	}
   729  	uu := u.(*rtype)
   730  	return directlyAssignable(uu, t) || implements(uu, t)
   731  }
   732  
   733  func (t *rtype) Comparable() bool {
   734  	return t.equal != nil
   735  }
   736  
   737  // implements reports whether the type V implements the interface type T.
   738  func implements(T, V *rtype) bool {
   739  	if T.Kind() != Interface {
   740  		return false
   741  	}
   742  	t := (*interfaceType)(unsafe.Pointer(T))
   743  	if len(t.methods) == 0 {
   744  		return true
   745  	}
   746  
   747  	// The same algorithm applies in both cases, but the
   748  	// method tables for an interface type and a concrete type
   749  	// are different, so the code is duplicated.
   750  	// In both cases the algorithm is a linear scan over the two
   751  	// lists - T's methods and V's methods - simultaneously.
   752  	// Since method tables are stored in a unique sorted order
   753  	// (alphabetical, with no duplicate method names), the scan
   754  	// through V's methods must hit a match for each of T's
   755  	// methods along the way, or else V does not implement T.
   756  	// This lets us run the scan in overall linear time instead of
   757  	// the quadratic time  a naive search would require.
   758  	// See also ../runtime/iface.go.
   759  	if V.Kind() == Interface {
   760  		v := (*interfaceType)(unsafe.Pointer(V))
   761  		i := 0
   762  		for j := 0; j < len(v.methods); j++ {
   763  			tm := &t.methods[i]
   764  			tmName := t.nameOff(tm.name)
   765  			vm := &v.methods[j]
   766  			vmName := V.nameOff(vm.name)
   767  			if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
   768  				if !tmName.isExported() {
   769  					tmPkgPath := tmName.pkgPath()
   770  					if tmPkgPath == "" {
   771  						tmPkgPath = t.pkgPath.name()
   772  					}
   773  					vmPkgPath := vmName.pkgPath()
   774  					if vmPkgPath == "" {
   775  						vmPkgPath = v.pkgPath.name()
   776  					}
   777  					if tmPkgPath != vmPkgPath {
   778  						continue
   779  					}
   780  				}
   781  				if i++; i >= len(t.methods) {
   782  					return true
   783  				}
   784  			}
   785  		}
   786  		return false
   787  	}
   788  
   789  	v := V.uncommon()
   790  	if v == nil {
   791  		return false
   792  	}
   793  	i := 0
   794  	vmethods := v.methods()
   795  	for j := 0; j < int(v.mcount); j++ {
   796  		tm := &t.methods[i]
   797  		tmName := t.nameOff(tm.name)
   798  		vm := vmethods[j]
   799  		vmName := V.nameOff(vm.name)
   800  		if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
   801  			if !tmName.isExported() {
   802  				tmPkgPath := tmName.pkgPath()
   803  				if tmPkgPath == "" {
   804  					tmPkgPath = t.pkgPath.name()
   805  				}
   806  				vmPkgPath := vmName.pkgPath()
   807  				if vmPkgPath == "" {
   808  					vmPkgPath = V.nameOff(v.pkgPath).name()
   809  				}
   810  				if tmPkgPath != vmPkgPath {
   811  					continue
   812  				}
   813  			}
   814  			if i++; i >= len(t.methods) {
   815  				return true
   816  			}
   817  		}
   818  	}
   819  	return false
   820  }
   821  
   822  // directlyAssignable reports whether a value x of type V can be directly
   823  // assigned (using memmove) to a value of type T.
   824  // https://golang.org/doc/go_spec.html#Assignability
   825  // Ignoring the interface rules (implemented elsewhere)
   826  // and the ideal constant rules (no ideal constants at run time).
   827  func directlyAssignable(T, V *rtype) bool {
   828  	// x's type V is identical to T?
   829  	if T == V {
   830  		return true
   831  	}
   832  
   833  	// Otherwise at least one of T and V must not be defined
   834  	// and they must have the same kind.
   835  	if T.hasName() && V.hasName() || T.Kind() != V.Kind() {
   836  		return false
   837  	}
   838  
   839  	// x's type T and V must  have identical underlying types.
   840  	return haveIdenticalUnderlyingType(T, V, true)
   841  }
   842  
   843  func haveIdenticalType(T, V Type, cmpTags bool) bool {
   844  	if cmpTags {
   845  		return T == V
   846  	}
   847  
   848  	if T.Name() != V.Name() || T.Kind() != V.Kind() {
   849  		return false
   850  	}
   851  
   852  	return haveIdenticalUnderlyingType(T.common(), V.common(), false)
   853  }
   854  
   855  func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
   856  	if T == V {
   857  		return true
   858  	}
   859  
   860  	kind := T.Kind()
   861  	if kind != V.Kind() {
   862  		return false
   863  	}
   864  
   865  	// Non-composite types of equal kind have same underlying type
   866  	// (the predefined instance of the type).
   867  	if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
   868  		return true
   869  	}
   870  
   871  	// Composite types.
   872  	switch kind {
   873  	case Array:
   874  		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   875  
   876  	case Chan:
   877  		// Special case:
   878  		// x is a bidirectional channel value, T is a channel type,
   879  		// and x's type V and T have identical element types.
   880  		if V.chanDir() == bothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
   881  			return true
   882  		}
   883  
   884  		// Otherwise continue test for identical underlying type.
   885  		return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   886  
   887  	case Func:
   888  		t := (*funcType)(unsafe.Pointer(T))
   889  		v := (*funcType)(unsafe.Pointer(V))
   890  		if t.outCount != v.outCount || t.inCount != v.inCount {
   891  			return false
   892  		}
   893  		for i := 0; i < t.NumIn(); i++ {
   894  			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
   895  				return false
   896  			}
   897  		}
   898  		for i := 0; i < t.NumOut(); i++ {
   899  			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
   900  				return false
   901  			}
   902  		}
   903  		return true
   904  
   905  	case Interface:
   906  		t := (*interfaceType)(unsafe.Pointer(T))
   907  		v := (*interfaceType)(unsafe.Pointer(V))
   908  		if len(t.methods) == 0 && len(v.methods) == 0 {
   909  			return true
   910  		}
   911  		// Might have the same methods but still
   912  		// need a run time conversion.
   913  		return false
   914  
   915  	case Map:
   916  		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   917  
   918  	case Ptr, Slice:
   919  		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   920  
   921  	case Struct:
   922  		t := (*structType)(unsafe.Pointer(T))
   923  		v := (*structType)(unsafe.Pointer(V))
   924  		if len(t.fields) != len(v.fields) {
   925  			return false
   926  		}
   927  		if t.pkgPath.name() != v.pkgPath.name() {
   928  			return false
   929  		}
   930  		for i := range t.fields {
   931  			tf := &t.fields[i]
   932  			vf := &v.fields[i]
   933  			if tf.name.name() != vf.name.name() {
   934  				return false
   935  			}
   936  			if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
   937  				return false
   938  			}
   939  			if cmpTags && tf.name.tag() != vf.name.tag() {
   940  				return false
   941  			}
   942  			if tf.offsetEmbed != vf.offsetEmbed {
   943  				return false
   944  			}
   945  		}
   946  		return true
   947  	}
   948  
   949  	return false
   950  }
   951  
   952  type structTypeUncommon struct {
   953  	structType
   954  	u uncommonType
   955  }
   956  
   957  // toType converts from a *rtype to a Type that can be returned
   958  // to the client of package reflect. In gc, the only concern is that
   959  // a nil *rtype must be replaced by a nil Type, but in gccgo this
   960  // function takes care of ensuring that multiple *rtype for the same
   961  // type are coalesced into a single Type.
   962  func toType(t *rtype) Type {
   963  	if t == nil {
   964  		return nil
   965  	}
   966  	return t
   967  }
   968  
   969  // ifaceIndir reports whether t is stored indirectly in an interface value.
   970  func ifaceIndir(t *rtype) bool {
   971  	return t.kind&kindDirectIface == 0
   972  }
   973  

View as plain text