Black Lives Matter. Support the Equal Justice Initiative.

Source file src/internal/reflectlite/type.go

Documentation: internal/reflectlite

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

View as plain text