Black Lives Matter. Support the Equal Justice Initiative.

Source file src/reflect/type.go

Documentation: reflect

     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 reflect implements run-time reflection, allowing a program to
     6  // manipulate objects with arbitrary types. The typical use is to take a value
     7  // with static type interface{} and extract its dynamic type information by
     8  // calling TypeOf, which returns a Type.
     9  //
    10  // A call to ValueOf returns a Value representing the run-time data.
    11  // Zero takes a Type and returns a Value representing a zero value
    12  // for that type.
    13  //
    14  // See "The Laws of Reflection" for an introduction to reflection in Go:
    15  // https://golang.org/doc/articles/laws_of_reflection.html
    16  package reflect
    17  
    18  import (
    19  	"internal/unsafeheader"
    20  	"strconv"
    21  	"sync"
    22  	"unicode"
    23  	"unicode/utf8"
    24  	"unsafe"
    25  )
    26  
    27  // Type is the representation of a Go type.
    28  //
    29  // Not all methods apply to all kinds of types. Restrictions,
    30  // if any, are noted in the documentation for each method.
    31  // Use the Kind method to find out the kind of type before
    32  // calling kind-specific methods. Calling a method
    33  // inappropriate to the kind of type causes a run-time panic.
    34  //
    35  // Type values are comparable, such as with the == operator,
    36  // so they can be used as map keys.
    37  // Two Type values are equal if they represent identical types.
    38  type Type interface {
    39  	// Methods applicable to all types.
    40  
    41  	// Align returns the alignment in bytes of a value of
    42  	// this type when allocated in memory.
    43  	Align() int
    44  
    45  	// FieldAlign returns the alignment in bytes of a value of
    46  	// this type when used as a field in a struct.
    47  	FieldAlign() int
    48  
    49  	// Method returns the i'th method in the type's method set.
    50  	// It panics if i is not in the range [0, NumMethod()).
    51  	//
    52  	// For a non-interface type T or *T, the returned Method's Type and Func
    53  	// fields describe a function whose first argument is the receiver.
    54  	//
    55  	// For an interface type, the returned Method's Type field gives the
    56  	// method signature, without a receiver, and the Func field is nil.
    57  	//
    58  	// Only exported methods are accessible and they are sorted in
    59  	// lexicographic order.
    60  	Method(int) Method
    61  
    62  	// MethodByName returns the method with that name in the type's
    63  	// method set and a boolean indicating if the method was found.
    64  	//
    65  	// For a non-interface type T or *T, the returned Method's Type and Func
    66  	// fields describe a function whose first argument is the receiver.
    67  	//
    68  	// For an interface type, the returned Method's Type field gives the
    69  	// method signature, without a receiver, and the Func field is nil.
    70  	MethodByName(string) (Method, bool)
    71  
    72  	// NumMethod returns the number of exported methods in the type's method set.
    73  	NumMethod() int
    74  
    75  	// Name returns the type's name within its package for a defined type.
    76  	// For other (non-defined) types it returns the empty string.
    77  	Name() string
    78  
    79  	// PkgPath returns a defined type's package path, that is, the import path
    80  	// that uniquely identifies the package, such as "encoding/base64".
    81  	// If the type was predeclared (string, error) or not defined (*T, struct{},
    82  	// []int, or A where A is an alias for a non-defined type), the package path
    83  	// will be the empty string.
    84  	PkgPath() string
    85  
    86  	// Size returns the number of bytes needed to store
    87  	// a value of the given type; it is analogous to unsafe.Sizeof.
    88  	Size() uintptr
    89  
    90  	// String returns a string representation of the type.
    91  	// The string representation may use shortened package names
    92  	// (e.g., base64 instead of "encoding/base64") and is not
    93  	// guaranteed to be unique among types. To test for type identity,
    94  	// compare the Types directly.
    95  	String() string
    96  
    97  	// Kind returns the specific kind of this type.
    98  	Kind() Kind
    99  
   100  	// Implements reports whether the type implements the interface type u.
   101  	Implements(u Type) bool
   102  
   103  	// AssignableTo reports whether a value of the type is assignable to type u.
   104  	AssignableTo(u Type) bool
   105  
   106  	// ConvertibleTo reports whether a value of the type is convertible to type u.
   107  	ConvertibleTo(u Type) bool
   108  
   109  	// Comparable reports whether values of this type are comparable.
   110  	Comparable() bool
   111  
   112  	// Methods applicable only to some types, depending on Kind.
   113  	// The methods allowed for each kind are:
   114  	//
   115  	//	Int*, Uint*, Float*, Complex*: Bits
   116  	//	Array: Elem, Len
   117  	//	Chan: ChanDir, Elem
   118  	//	Func: In, NumIn, Out, NumOut, IsVariadic.
   119  	//	Map: Key, Elem
   120  	//	Ptr: Elem
   121  	//	Slice: Elem
   122  	//	Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
   123  
   124  	// Bits returns the size of the type in bits.
   125  	// It panics if the type's Kind is not one of the
   126  	// sized or unsized Int, Uint, Float, or Complex kinds.
   127  	Bits() int
   128  
   129  	// ChanDir returns a channel type's direction.
   130  	// It panics if the type's Kind is not Chan.
   131  	ChanDir() ChanDir
   132  
   133  	// IsVariadic reports whether a function type's final input parameter
   134  	// is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
   135  	// implicit actual type []T.
   136  	//
   137  	// For concreteness, if t represents func(x int, y ... float64), then
   138  	//
   139  	//	t.NumIn() == 2
   140  	//	t.In(0) is the reflect.Type for "int"
   141  	//	t.In(1) is the reflect.Type for "[]float64"
   142  	//	t.IsVariadic() == true
   143  	//
   144  	// IsVariadic panics if the type's Kind is not Func.
   145  	IsVariadic() bool
   146  
   147  	// Elem returns a type's element type.
   148  	// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
   149  	Elem() Type
   150  
   151  	// Field returns a struct type's i'th field.
   152  	// It panics if the type's Kind is not Struct.
   153  	// It panics if i is not in the range [0, NumField()).
   154  	Field(i int) StructField
   155  
   156  	// FieldByIndex returns the nested field corresponding
   157  	// to the index sequence. It is equivalent to calling Field
   158  	// successively for each index i.
   159  	// It panics if the type's Kind is not Struct.
   160  	FieldByIndex(index []int) StructField
   161  
   162  	// FieldByName returns the struct field with the given name
   163  	// and a boolean indicating if the field was found.
   164  	FieldByName(name string) (StructField, bool)
   165  
   166  	// FieldByNameFunc returns the struct field with a name
   167  	// that satisfies the match function and a boolean indicating if
   168  	// the field was found.
   169  	//
   170  	// FieldByNameFunc considers the fields in the struct itself
   171  	// and then the fields in any embedded structs, in breadth first order,
   172  	// stopping at the shallowest nesting depth containing one or more
   173  	// fields satisfying the match function. If multiple fields at that depth
   174  	// satisfy the match function, they cancel each other
   175  	// and FieldByNameFunc returns no match.
   176  	// This behavior mirrors Go's handling of name lookup in
   177  	// structs containing embedded fields.
   178  	FieldByNameFunc(match func(string) bool) (StructField, bool)
   179  
   180  	// In returns the type of a function type's i'th input parameter.
   181  	// It panics if the type's Kind is not Func.
   182  	// It panics if i is not in the range [0, NumIn()).
   183  	In(i int) Type
   184  
   185  	// Key returns a map type's key type.
   186  	// It panics if the type's Kind is not Map.
   187  	Key() Type
   188  
   189  	// Len returns an array type's length.
   190  	// It panics if the type's Kind is not Array.
   191  	Len() int
   192  
   193  	// NumField returns a struct type's field count.
   194  	// It panics if the type's Kind is not Struct.
   195  	NumField() int
   196  
   197  	// NumIn returns a function type's input parameter count.
   198  	// It panics if the type's Kind is not Func.
   199  	NumIn() int
   200  
   201  	// NumOut returns a function type's output parameter count.
   202  	// It panics if the type's Kind is not Func.
   203  	NumOut() int
   204  
   205  	// Out returns the type of a function type's i'th output parameter.
   206  	// It panics if the type's Kind is not Func.
   207  	// It panics if i is not in the range [0, NumOut()).
   208  	Out(i int) Type
   209  
   210  	common() *rtype
   211  	uncommon() *uncommonType
   212  }
   213  
   214  // BUG(rsc): FieldByName and related functions consider struct field names to be equal
   215  // if the names are equal, even if they are unexported names originating
   216  // in different packages. The practical effect of this is that the result of
   217  // t.FieldByName("x") is not well defined if the struct type t contains
   218  // multiple fields named x (embedded from different packages).
   219  // FieldByName may return one of the fields named x or may report that there are none.
   220  // See https://golang.org/issue/4876 for more details.
   221  
   222  /*
   223   * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
   224   * A few are known to ../runtime/type.go to convey to debuggers.
   225   * They are also known to ../runtime/type.go.
   226   */
   227  
   228  // A Kind represents the specific kind of type that a Type represents.
   229  // The zero Kind is not a valid kind.
   230  type Kind uint
   231  
   232  const (
   233  	Invalid Kind = iota
   234  	Bool
   235  	Int
   236  	Int8
   237  	Int16
   238  	Int32
   239  	Int64
   240  	Uint
   241  	Uint8
   242  	Uint16
   243  	Uint32
   244  	Uint64
   245  	Uintptr
   246  	Float32
   247  	Float64
   248  	Complex64
   249  	Complex128
   250  	Array
   251  	Chan
   252  	Func
   253  	Interface
   254  	Map
   255  	Ptr
   256  	Slice
   257  	String
   258  	Struct
   259  	UnsafePointer
   260  )
   261  
   262  // tflag is used by an rtype to signal what extra type information is
   263  // available in the memory directly following the rtype value.
   264  //
   265  // tflag values must be kept in sync with copies in:
   266  //	cmd/compile/internal/gc/reflect.go
   267  //	cmd/link/internal/ld/decodesym.go
   268  //	runtime/type.go
   269  type tflag uint8
   270  
   271  const (
   272  	// tflagUncommon means that there is a pointer, *uncommonType,
   273  	// just beyond the outer type structure.
   274  	//
   275  	// For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0,
   276  	// then t has uncommonType data and it can be accessed as:
   277  	//
   278  	//	type tUncommon struct {
   279  	//		structType
   280  	//		u uncommonType
   281  	//	}
   282  	//	u := &(*tUncommon)(unsafe.Pointer(t)).u
   283  	tflagUncommon tflag = 1 << 0
   284  
   285  	// tflagExtraStar means the name in the str field has an
   286  	// extraneous '*' prefix. This is because for most types T in
   287  	// a program, the type *T also exists and reusing the str data
   288  	// saves binary size.
   289  	tflagExtraStar tflag = 1 << 1
   290  
   291  	// tflagNamed means the type has a name.
   292  	tflagNamed tflag = 1 << 2
   293  
   294  	// tflagRegularMemory means that equal and hash functions can treat
   295  	// this type as a single region of t.size bytes.
   296  	tflagRegularMemory tflag = 1 << 3
   297  )
   298  
   299  // rtype is the common implementation of most values.
   300  // It is embedded in other struct types.
   301  //
   302  // rtype must be kept in sync with ../runtime/type.go:/^type._type.
   303  type rtype struct {
   304  	size       uintptr
   305  	ptrdata    uintptr // number of bytes in the type that can contain pointers
   306  	hash       uint32  // hash of type; avoids computation in hash tables
   307  	tflag      tflag   // extra type information flags
   308  	align      uint8   // alignment of variable with this type
   309  	fieldAlign uint8   // alignment of struct field with this type
   310  	kind       uint8   // enumeration for C
   311  	// function for comparing objects of this type
   312  	// (ptr to object A, ptr to object B) -> ==?
   313  	equal     func(unsafe.Pointer, unsafe.Pointer) bool
   314  	gcdata    *byte   // garbage collection data
   315  	str       nameOff // string form
   316  	ptrToThis typeOff // type for pointer to this type, may be zero
   317  }
   318  
   319  // Method on non-interface type
   320  type method struct {
   321  	name nameOff // name of method
   322  	mtyp typeOff // method type (without receiver)
   323  	ifn  textOff // fn used in interface call (one-word receiver)
   324  	tfn  textOff // fn used for normal method call
   325  }
   326  
   327  // uncommonType is present only for defined types or types with methods
   328  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   329  // Using a pointer to this struct reduces the overall size required
   330  // to describe a non-defined type with no methods.
   331  type uncommonType struct {
   332  	pkgPath nameOff // import path; empty for built-in types like int, string
   333  	mcount  uint16  // number of methods
   334  	xcount  uint16  // number of exported methods
   335  	moff    uint32  // offset from this uncommontype to [mcount]method
   336  	_       uint32  // unused
   337  }
   338  
   339  // ChanDir represents a channel type's direction.
   340  type ChanDir int
   341  
   342  const (
   343  	RecvDir ChanDir             = 1 << iota // <-chan
   344  	SendDir                                 // chan<-
   345  	BothDir = RecvDir | SendDir             // chan
   346  )
   347  
   348  // arrayType represents a fixed array type.
   349  type arrayType struct {
   350  	rtype
   351  	elem  *rtype // array element type
   352  	slice *rtype // slice type
   353  	len   uintptr
   354  }
   355  
   356  // chanType represents a channel type.
   357  type chanType struct {
   358  	rtype
   359  	elem *rtype  // channel element type
   360  	dir  uintptr // channel direction (ChanDir)
   361  }
   362  
   363  // funcType represents a function type.
   364  //
   365  // A *rtype for each in and out parameter is stored in an array that
   366  // directly follows the funcType (and possibly its uncommonType). So
   367  // a function type with one method, one input, and one output is:
   368  //
   369  //	struct {
   370  //		funcType
   371  //		uncommonType
   372  //		[2]*rtype    // [0] is in, [1] is out
   373  //	}
   374  type funcType struct {
   375  	rtype
   376  	inCount  uint16
   377  	outCount uint16 // top bit is set if last input parameter is ...
   378  }
   379  
   380  // imethod represents a method on an interface type
   381  type imethod struct {
   382  	name nameOff // name of method
   383  	typ  typeOff // .(*FuncType) underneath
   384  }
   385  
   386  // interfaceType represents an interface type.
   387  type interfaceType struct {
   388  	rtype
   389  	pkgPath name      // import path
   390  	methods []imethod // sorted by hash
   391  }
   392  
   393  // mapType represents a map type.
   394  type mapType struct {
   395  	rtype
   396  	key    *rtype // map key type
   397  	elem   *rtype // map element (value) type
   398  	bucket *rtype // internal bucket structure
   399  	// function for hashing keys (ptr to key, seed) -> hash
   400  	hasher     func(unsafe.Pointer, uintptr) uintptr
   401  	keysize    uint8  // size of key slot
   402  	valuesize  uint8  // size of value slot
   403  	bucketsize uint16 // size of bucket
   404  	flags      uint32
   405  }
   406  
   407  // ptrType represents a pointer type.
   408  type ptrType struct {
   409  	rtype
   410  	elem *rtype // pointer element (pointed at) type
   411  }
   412  
   413  // sliceType represents a slice type.
   414  type sliceType struct {
   415  	rtype
   416  	elem *rtype // slice element type
   417  }
   418  
   419  // Struct field
   420  type structField struct {
   421  	name        name    // name is always non-empty
   422  	typ         *rtype  // type of field
   423  	offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
   424  }
   425  
   426  func (f *structField) offset() uintptr {
   427  	return f.offsetEmbed >> 1
   428  }
   429  
   430  func (f *structField) embedded() bool {
   431  	return f.offsetEmbed&1 != 0
   432  }
   433  
   434  // structType represents a struct type.
   435  type structType struct {
   436  	rtype
   437  	pkgPath name
   438  	fields  []structField // sorted by offset
   439  }
   440  
   441  // name is an encoded type name with optional extra data.
   442  //
   443  // The first byte is a bit field containing:
   444  //
   445  //	1<<0 the name is exported
   446  //	1<<1 tag data follows the name
   447  //	1<<2 pkgPath nameOff follows the name and tag
   448  //
   449  // The next two bytes are the data length:
   450  //
   451  //	 l := uint16(data[1])<<8 | uint16(data[2])
   452  //
   453  // Bytes [3:3+l] are the string data.
   454  //
   455  // If tag data follows then bytes 3+l and 3+l+1 are the tag length,
   456  // with the data following.
   457  //
   458  // If the import path follows, then 4 bytes at the end of
   459  // the data form a nameOff. The import path is only set for concrete
   460  // methods that are defined in a different package than their type.
   461  //
   462  // If a name starts with "*", then the exported bit represents
   463  // whether the pointed to type is exported.
   464  type name struct {
   465  	bytes *byte
   466  }
   467  
   468  func (n name) data(off int, whySafe string) *byte {
   469  	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
   470  }
   471  
   472  func (n name) isExported() bool {
   473  	return (*n.bytes)&(1<<0) != 0
   474  }
   475  
   476  func (n name) nameLen() int {
   477  	return int(uint16(*n.data(1, "name len field"))<<8 | uint16(*n.data(2, "name len field")))
   478  }
   479  
   480  func (n name) tagLen() int {
   481  	if *n.data(0, "name flag field")&(1<<1) == 0 {
   482  		return 0
   483  	}
   484  	off := 3 + n.nameLen()
   485  	return int(uint16(*n.data(off, "name taglen field"))<<8 | uint16(*n.data(off+1, "name taglen field")))
   486  }
   487  
   488  func (n name) name() (s string) {
   489  	if n.bytes == nil {
   490  		return
   491  	}
   492  	b := (*[4]byte)(unsafe.Pointer(n.bytes))
   493  
   494  	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
   495  	hdr.Data = unsafe.Pointer(&b[3])
   496  	hdr.Len = int(b[1])<<8 | int(b[2])
   497  	return s
   498  }
   499  
   500  func (n name) tag() (s string) {
   501  	tl := n.tagLen()
   502  	if tl == 0 {
   503  		return ""
   504  	}
   505  	nl := n.nameLen()
   506  	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
   507  	hdr.Data = unsafe.Pointer(n.data(3+nl+2, "non-empty string"))
   508  	hdr.Len = tl
   509  	return s
   510  }
   511  
   512  func (n name) pkgPath() string {
   513  	if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
   514  		return ""
   515  	}
   516  	off := 3 + n.nameLen()
   517  	if tl := n.tagLen(); tl > 0 {
   518  		off += 2 + tl
   519  	}
   520  	var nameOff int32
   521  	// Note that this field may not be aligned in memory,
   522  	// so we cannot use a direct int32 assignment here.
   523  	copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
   524  	pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
   525  	return pkgPathName.name()
   526  }
   527  
   528  func newName(n, tag string, exported bool) name {
   529  	if len(n) > 1<<16-1 {
   530  		panic("reflect.nameFrom: name too long: " + n)
   531  	}
   532  	if len(tag) > 1<<16-1 {
   533  		panic("reflect.nameFrom: tag too long: " + tag)
   534  	}
   535  
   536  	var bits byte
   537  	l := 1 + 2 + len(n)
   538  	if exported {
   539  		bits |= 1 << 0
   540  	}
   541  	if len(tag) > 0 {
   542  		l += 2 + len(tag)
   543  		bits |= 1 << 1
   544  	}
   545  
   546  	b := make([]byte, l)
   547  	b[0] = bits
   548  	b[1] = uint8(len(n) >> 8)
   549  	b[2] = uint8(len(n))
   550  	copy(b[3:], n)
   551  	if len(tag) > 0 {
   552  		tb := b[3+len(n):]
   553  		tb[0] = uint8(len(tag) >> 8)
   554  		tb[1] = uint8(len(tag))
   555  		copy(tb[2:], tag)
   556  	}
   557  
   558  	return name{bytes: &b[0]}
   559  }
   560  
   561  /*
   562   * The compiler knows the exact layout of all the data structures above.
   563   * The compiler does not know about the data structures and methods below.
   564   */
   565  
   566  // Method represents a single method.
   567  type Method struct {
   568  	// Name is the method name.
   569  	// PkgPath is the package path that qualifies a lower case (unexported)
   570  	// method name. It is empty for upper case (exported) method names.
   571  	// The combination of PkgPath and Name uniquely identifies a method
   572  	// in a method set.
   573  	// See https://golang.org/ref/spec#Uniqueness_of_identifiers
   574  	Name    string
   575  	PkgPath string
   576  
   577  	Type  Type  // method type
   578  	Func  Value // func with receiver as first argument
   579  	Index int   // index for Type.Method
   580  }
   581  
   582  const (
   583  	kindDirectIface = 1 << 5
   584  	kindGCProg      = 1 << 6 // Type.gc points to GC program
   585  	kindMask        = (1 << 5) - 1
   586  )
   587  
   588  // String returns the name of k.
   589  func (k Kind) String() string {
   590  	if int(k) < len(kindNames) {
   591  		return kindNames[k]
   592  	}
   593  	return "kind" + strconv.Itoa(int(k))
   594  }
   595  
   596  var kindNames = []string{
   597  	Invalid:       "invalid",
   598  	Bool:          "bool",
   599  	Int:           "int",
   600  	Int8:          "int8",
   601  	Int16:         "int16",
   602  	Int32:         "int32",
   603  	Int64:         "int64",
   604  	Uint:          "uint",
   605  	Uint8:         "uint8",
   606  	Uint16:        "uint16",
   607  	Uint32:        "uint32",
   608  	Uint64:        "uint64",
   609  	Uintptr:       "uintptr",
   610  	Float32:       "float32",
   611  	Float64:       "float64",
   612  	Complex64:     "complex64",
   613  	Complex128:    "complex128",
   614  	Array:         "array",
   615  	Chan:          "chan",
   616  	Func:          "func",
   617  	Interface:     "interface",
   618  	Map:           "map",
   619  	Ptr:           "ptr",
   620  	Slice:         "slice",
   621  	String:        "string",
   622  	Struct:        "struct",
   623  	UnsafePointer: "unsafe.Pointer",
   624  }
   625  
   626  func (t *uncommonType) methods() []method {
   627  	if t.mcount == 0 {
   628  		return nil
   629  	}
   630  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
   631  }
   632  
   633  func (t *uncommonType) exportedMethods() []method {
   634  	if t.xcount == 0 {
   635  		return nil
   636  	}
   637  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
   638  }
   639  
   640  // resolveNameOff resolves a name offset from a base pointer.
   641  // The (*rtype).nameOff method is a convenience wrapper for this function.
   642  // Implemented in the runtime package.
   643  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
   644  
   645  // resolveTypeOff resolves an *rtype offset from a base type.
   646  // The (*rtype).typeOff method is a convenience wrapper for this function.
   647  // Implemented in the runtime package.
   648  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   649  
   650  // resolveTextOff resolves a function pointer offset from a base type.
   651  // The (*rtype).textOff method is a convenience wrapper for this function.
   652  // Implemented in the runtime package.
   653  func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   654  
   655  // addReflectOff adds a pointer to the reflection lookup map in the runtime.
   656  // It returns a new ID that can be used as a typeOff or textOff, and will
   657  // be resolved correctly. Implemented in the runtime package.
   658  func addReflectOff(ptr unsafe.Pointer) int32
   659  
   660  // resolveReflectName adds a name to the reflection lookup map in the runtime.
   661  // It returns a new nameOff that can be used to refer to the pointer.
   662  func resolveReflectName(n name) nameOff {
   663  	return nameOff(addReflectOff(unsafe.Pointer(n.bytes)))
   664  }
   665  
   666  // resolveReflectType adds a *rtype to the reflection lookup map in the runtime.
   667  // It returns a new typeOff that can be used to refer to the pointer.
   668  func resolveReflectType(t *rtype) typeOff {
   669  	return typeOff(addReflectOff(unsafe.Pointer(t)))
   670  }
   671  
   672  // resolveReflectText adds a function pointer to the reflection lookup map in
   673  // the runtime. It returns a new textOff that can be used to refer to the
   674  // pointer.
   675  func resolveReflectText(ptr unsafe.Pointer) textOff {
   676  	return textOff(addReflectOff(ptr))
   677  }
   678  
   679  type nameOff int32 // offset to a name
   680  type typeOff int32 // offset to an *rtype
   681  type textOff int32 // offset from top of text section
   682  
   683  func (t *rtype) nameOff(off nameOff) name {
   684  	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
   685  }
   686  
   687  func (t *rtype) typeOff(off typeOff) *rtype {
   688  	return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
   689  }
   690  
   691  func (t *rtype) textOff(off textOff) unsafe.Pointer {
   692  	return resolveTextOff(unsafe.Pointer(t), int32(off))
   693  }
   694  
   695  func (t *rtype) uncommon() *uncommonType {
   696  	if t.tflag&tflagUncommon == 0 {
   697  		return nil
   698  	}
   699  	switch t.Kind() {
   700  	case Struct:
   701  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   702  	case Ptr:
   703  		type u struct {
   704  			ptrType
   705  			u uncommonType
   706  		}
   707  		return &(*u)(unsafe.Pointer(t)).u
   708  	case Func:
   709  		type u struct {
   710  			funcType
   711  			u uncommonType
   712  		}
   713  		return &(*u)(unsafe.Pointer(t)).u
   714  	case Slice:
   715  		type u struct {
   716  			sliceType
   717  			u uncommonType
   718  		}
   719  		return &(*u)(unsafe.Pointer(t)).u
   720  	case Array:
   721  		type u struct {
   722  			arrayType
   723  			u uncommonType
   724  		}
   725  		return &(*u)(unsafe.Pointer(t)).u
   726  	case Chan:
   727  		type u struct {
   728  			chanType
   729  			u uncommonType
   730  		}
   731  		return &(*u)(unsafe.Pointer(t)).u
   732  	case Map:
   733  		type u struct {
   734  			mapType
   735  			u uncommonType
   736  		}
   737  		return &(*u)(unsafe.Pointer(t)).u
   738  	case Interface:
   739  		type u struct {
   740  			interfaceType
   741  			u uncommonType
   742  		}
   743  		return &(*u)(unsafe.Pointer(t)).u
   744  	default:
   745  		type u struct {
   746  			rtype
   747  			u uncommonType
   748  		}
   749  		return &(*u)(unsafe.Pointer(t)).u
   750  	}
   751  }
   752  
   753  func (t *rtype) String() string {
   754  	s := t.nameOff(t.str).name()
   755  	if t.tflag&tflagExtraStar != 0 {
   756  		return s[1:]
   757  	}
   758  	return s
   759  }
   760  
   761  func (t *rtype) Size() uintptr { return t.size }
   762  
   763  func (t *rtype) Bits() int {
   764  	if t == nil {
   765  		panic("reflect: Bits of nil Type")
   766  	}
   767  	k := t.Kind()
   768  	if k < Int || k > Complex128 {
   769  		panic("reflect: Bits of non-arithmetic Type " + t.String())
   770  	}
   771  	return int(t.size) * 8
   772  }
   773  
   774  func (t *rtype) Align() int { return int(t.align) }
   775  
   776  func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
   777  
   778  func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
   779  
   780  func (t *rtype) pointers() bool { return t.ptrdata != 0 }
   781  
   782  func (t *rtype) common() *rtype { return t }
   783  
   784  func (t *rtype) exportedMethods() []method {
   785  	ut := t.uncommon()
   786  	if ut == nil {
   787  		return nil
   788  	}
   789  	return ut.exportedMethods()
   790  }
   791  
   792  func (t *rtype) NumMethod() int {
   793  	if t.Kind() == Interface {
   794  		tt := (*interfaceType)(unsafe.Pointer(t))
   795  		return tt.NumMethod()
   796  	}
   797  	return len(t.exportedMethods())
   798  }
   799  
   800  func (t *rtype) Method(i int) (m Method) {
   801  	if t.Kind() == Interface {
   802  		tt := (*interfaceType)(unsafe.Pointer(t))
   803  		return tt.Method(i)
   804  	}
   805  	methods := t.exportedMethods()
   806  	if i < 0 || i >= len(methods) {
   807  		panic("reflect: Method index out of range")
   808  	}
   809  	p := methods[i]
   810  	pname := t.nameOff(p.name)
   811  	m.Name = pname.name()
   812  	fl := flag(Func)
   813  	mtyp := t.typeOff(p.mtyp)
   814  	ft := (*funcType)(unsafe.Pointer(mtyp))
   815  	in := make([]Type, 0, 1+len(ft.in()))
   816  	in = append(in, t)
   817  	for _, arg := range ft.in() {
   818  		in = append(in, arg)
   819  	}
   820  	out := make([]Type, 0, len(ft.out()))
   821  	for _, ret := range ft.out() {
   822  		out = append(out, ret)
   823  	}
   824  	mt := FuncOf(in, out, ft.IsVariadic())
   825  	m.Type = mt
   826  	tfn := t.textOff(p.tfn)
   827  	fn := unsafe.Pointer(&tfn)
   828  	m.Func = Value{mt.(*rtype), fn, fl}
   829  
   830  	m.Index = i
   831  	return m
   832  }
   833  
   834  func (t *rtype) MethodByName(name string) (m Method, ok bool) {
   835  	if t.Kind() == Interface {
   836  		tt := (*interfaceType)(unsafe.Pointer(t))
   837  		return tt.MethodByName(name)
   838  	}
   839  	ut := t.uncommon()
   840  	if ut == nil {
   841  		return Method{}, false
   842  	}
   843  	// TODO(mdempsky): Binary search.
   844  	for i, p := range ut.exportedMethods() {
   845  		if t.nameOff(p.name).name() == name {
   846  			return t.Method(i), true
   847  		}
   848  	}
   849  	return Method{}, false
   850  }
   851  
   852  func (t *rtype) PkgPath() string {
   853  	if t.tflag&tflagNamed == 0 {
   854  		return ""
   855  	}
   856  	ut := t.uncommon()
   857  	if ut == nil {
   858  		return ""
   859  	}
   860  	return t.nameOff(ut.pkgPath).name()
   861  }
   862  
   863  func (t *rtype) hasName() bool {
   864  	return t.tflag&tflagNamed != 0
   865  }
   866  
   867  func (t *rtype) Name() string {
   868  	if !t.hasName() {
   869  		return ""
   870  	}
   871  	s := t.String()
   872  	i := len(s) - 1
   873  	for i >= 0 && s[i] != '.' {
   874  		i--
   875  	}
   876  	return s[i+1:]
   877  }
   878  
   879  func (t *rtype) ChanDir() ChanDir {
   880  	if t.Kind() != Chan {
   881  		panic("reflect: ChanDir of non-chan type " + t.String())
   882  	}
   883  	tt := (*chanType)(unsafe.Pointer(t))
   884  	return ChanDir(tt.dir)
   885  }
   886  
   887  func (t *rtype) IsVariadic() bool {
   888  	if t.Kind() != Func {
   889  		panic("reflect: IsVariadic of non-func type " + t.String())
   890  	}
   891  	tt := (*funcType)(unsafe.Pointer(t))
   892  	return tt.outCount&(1<<15) != 0
   893  }
   894  
   895  func (t *rtype) Elem() Type {
   896  	switch t.Kind() {
   897  	case Array:
   898  		tt := (*arrayType)(unsafe.Pointer(t))
   899  		return toType(tt.elem)
   900  	case Chan:
   901  		tt := (*chanType)(unsafe.Pointer(t))
   902  		return toType(tt.elem)
   903  	case Map:
   904  		tt := (*mapType)(unsafe.Pointer(t))
   905  		return toType(tt.elem)
   906  	case Ptr:
   907  		tt := (*ptrType)(unsafe.Pointer(t))
   908  		return toType(tt.elem)
   909  	case Slice:
   910  		tt := (*sliceType)(unsafe.Pointer(t))
   911  		return toType(tt.elem)
   912  	}
   913  	panic("reflect: Elem of invalid type " + t.String())
   914  }
   915  
   916  func (t *rtype) Field(i int) StructField {
   917  	if t.Kind() != Struct {
   918  		panic("reflect: Field of non-struct type " + t.String())
   919  	}
   920  	tt := (*structType)(unsafe.Pointer(t))
   921  	return tt.Field(i)
   922  }
   923  
   924  func (t *rtype) FieldByIndex(index []int) StructField {
   925  	if t.Kind() != Struct {
   926  		panic("reflect: FieldByIndex of non-struct type " + t.String())
   927  	}
   928  	tt := (*structType)(unsafe.Pointer(t))
   929  	return tt.FieldByIndex(index)
   930  }
   931  
   932  func (t *rtype) FieldByName(name string) (StructField, bool) {
   933  	if t.Kind() != Struct {
   934  		panic("reflect: FieldByName of non-struct type " + t.String())
   935  	}
   936  	tt := (*structType)(unsafe.Pointer(t))
   937  	return tt.FieldByName(name)
   938  }
   939  
   940  func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
   941  	if t.Kind() != Struct {
   942  		panic("reflect: FieldByNameFunc of non-struct type " + t.String())
   943  	}
   944  	tt := (*structType)(unsafe.Pointer(t))
   945  	return tt.FieldByNameFunc(match)
   946  }
   947  
   948  func (t *rtype) In(i int) Type {
   949  	if t.Kind() != Func {
   950  		panic("reflect: In of non-func type " + t.String())
   951  	}
   952  	tt := (*funcType)(unsafe.Pointer(t))
   953  	return toType(tt.in()[i])
   954  }
   955  
   956  func (t *rtype) Key() Type {
   957  	if t.Kind() != Map {
   958  		panic("reflect: Key of non-map type " + t.String())
   959  	}
   960  	tt := (*mapType)(unsafe.Pointer(t))
   961  	return toType(tt.key)
   962  }
   963  
   964  func (t *rtype) Len() int {
   965  	if t.Kind() != Array {
   966  		panic("reflect: Len of non-array type " + t.String())
   967  	}
   968  	tt := (*arrayType)(unsafe.Pointer(t))
   969  	return int(tt.len)
   970  }
   971  
   972  func (t *rtype) NumField() int {
   973  	if t.Kind() != Struct {
   974  		panic("reflect: NumField of non-struct type " + t.String())
   975  	}
   976  	tt := (*structType)(unsafe.Pointer(t))
   977  	return len(tt.fields)
   978  }
   979  
   980  func (t *rtype) NumIn() int {
   981  	if t.Kind() != Func {
   982  		panic("reflect: NumIn of non-func type " + t.String())
   983  	}
   984  	tt := (*funcType)(unsafe.Pointer(t))
   985  	return int(tt.inCount)
   986  }
   987  
   988  func (t *rtype) NumOut() int {
   989  	if t.Kind() != Func {
   990  		panic("reflect: NumOut of non-func type " + t.String())
   991  	}
   992  	tt := (*funcType)(unsafe.Pointer(t))
   993  	return len(tt.out())
   994  }
   995  
   996  func (t *rtype) Out(i int) Type {
   997  	if t.Kind() != Func {
   998  		panic("reflect: Out of non-func type " + t.String())
   999  	}
  1000  	tt := (*funcType)(unsafe.Pointer(t))
  1001  	return toType(tt.out()[i])
  1002  }
  1003  
  1004  func (t *funcType) in() []*rtype {
  1005  	uadd := unsafe.Sizeof(*t)
  1006  	if t.tflag&tflagUncommon != 0 {
  1007  		uadd += unsafe.Sizeof(uncommonType{})
  1008  	}
  1009  	if t.inCount == 0 {
  1010  		return nil
  1011  	}
  1012  	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
  1013  }
  1014  
  1015  func (t *funcType) out() []*rtype {
  1016  	uadd := unsafe.Sizeof(*t)
  1017  	if t.tflag&tflagUncommon != 0 {
  1018  		uadd += unsafe.Sizeof(uncommonType{})
  1019  	}
  1020  	outCount := t.outCount & (1<<15 - 1)
  1021  	if outCount == 0 {
  1022  		return nil
  1023  	}
  1024  	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
  1025  }
  1026  
  1027  // add returns p+x.
  1028  //
  1029  // The whySafe string is ignored, so that the function still inlines
  1030  // as efficiently as p+x, but all call sites should use the string to
  1031  // record why the addition is safe, which is to say why the addition
  1032  // does not cause x to advance to the very end of p's allocation
  1033  // and therefore point incorrectly at the next block in memory.
  1034  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
  1035  	return unsafe.Pointer(uintptr(p) + x)
  1036  }
  1037  
  1038  func (d ChanDir) String() string {
  1039  	switch d {
  1040  	case SendDir:
  1041  		return "chan<-"
  1042  	case RecvDir:
  1043  		return "<-chan"
  1044  	case BothDir:
  1045  		return "chan"
  1046  	}
  1047  	return "ChanDir" + strconv.Itoa(int(d))
  1048  }
  1049  
  1050  // Method returns the i'th method in the type's method set.
  1051  func (t *interfaceType) Method(i int) (m Method) {
  1052  	if i < 0 || i >= len(t.methods) {
  1053  		return
  1054  	}
  1055  	p := &t.methods[i]
  1056  	pname := t.nameOff(p.name)
  1057  	m.Name = pname.name()
  1058  	if !pname.isExported() {
  1059  		m.PkgPath = pname.pkgPath()
  1060  		if m.PkgPath == "" {
  1061  			m.PkgPath = t.pkgPath.name()
  1062  		}
  1063  	}
  1064  	m.Type = toType(t.typeOff(p.typ))
  1065  	m.Index = i
  1066  	return
  1067  }
  1068  
  1069  // NumMethod returns the number of interface methods in the type's method set.
  1070  func (t *interfaceType) NumMethod() int { return len(t.methods) }
  1071  
  1072  // MethodByName method with the given name in the type's method set.
  1073  func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
  1074  	if t == nil {
  1075  		return
  1076  	}
  1077  	var p *imethod
  1078  	for i := range t.methods {
  1079  		p = &t.methods[i]
  1080  		if t.nameOff(p.name).name() == name {
  1081  			return t.Method(i), true
  1082  		}
  1083  	}
  1084  	return
  1085  }
  1086  
  1087  // A StructField describes a single field in a struct.
  1088  type StructField struct {
  1089  	// Name is the field name.
  1090  	Name string
  1091  	// PkgPath is the package path that qualifies a lower case (unexported)
  1092  	// field name. It is empty for upper case (exported) field names.
  1093  	// See https://golang.org/ref/spec#Uniqueness_of_identifiers
  1094  	PkgPath string
  1095  
  1096  	Type      Type      // field type
  1097  	Tag       StructTag // field tag string
  1098  	Offset    uintptr   // offset within struct, in bytes
  1099  	Index     []int     // index sequence for Type.FieldByIndex
  1100  	Anonymous bool      // is an embedded field
  1101  }
  1102  
  1103  // A StructTag is the tag string in a struct field.
  1104  //
  1105  // By convention, tag strings are a concatenation of
  1106  // optionally space-separated key:"value" pairs.
  1107  // Each key is a non-empty string consisting of non-control
  1108  // characters other than space (U+0020 ' '), quote (U+0022 '"'),
  1109  // and colon (U+003A ':').  Each value is quoted using U+0022 '"'
  1110  // characters and Go string literal syntax.
  1111  type StructTag string
  1112  
  1113  // Get returns the value associated with key in the tag string.
  1114  // If there is no such key in the tag, Get returns the empty string.
  1115  // If the tag does not have the conventional format, the value
  1116  // returned by Get is unspecified. To determine whether a tag is
  1117  // explicitly set to the empty string, use Lookup.
  1118  func (tag StructTag) Get(key string) string {
  1119  	v, _ := tag.Lookup(key)
  1120  	return v
  1121  }
  1122  
  1123  // Lookup returns the value associated with key in the tag string.
  1124  // If the key is present in the tag the value (which may be empty)
  1125  // is returned. Otherwise the returned value will be the empty string.
  1126  // The ok return value reports whether the value was explicitly set in
  1127  // the tag string. If the tag does not have the conventional format,
  1128  // the value returned by Lookup is unspecified.
  1129  func (tag StructTag) Lookup(key string) (value string, ok bool) {
  1130  	// When modifying this code, also update the validateStructTag code
  1131  	// in cmd/vet/structtag.go.
  1132  
  1133  	for tag != "" {
  1134  		// Skip leading space.
  1135  		i := 0
  1136  		for i < len(tag) && tag[i] == ' ' {
  1137  			i++
  1138  		}
  1139  		tag = tag[i:]
  1140  		if tag == "" {
  1141  			break
  1142  		}
  1143  
  1144  		// Scan to colon. A space, a quote or a control character is a syntax error.
  1145  		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
  1146  		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
  1147  		// as it is simpler to inspect the tag's bytes than the tag's runes.
  1148  		i = 0
  1149  		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
  1150  			i++
  1151  		}
  1152  		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
  1153  			break
  1154  		}
  1155  		name := string(tag[:i])
  1156  		tag = tag[i+1:]
  1157  
  1158  		// Scan quoted string to find value.
  1159  		i = 1
  1160  		for i < len(tag) && tag[i] != '"' {
  1161  			if tag[i] == '\\' {
  1162  				i++
  1163  			}
  1164  			i++
  1165  		}
  1166  		if i >= len(tag) {
  1167  			break
  1168  		}
  1169  		qvalue := string(tag[:i+1])
  1170  		tag = tag[i+1:]
  1171  
  1172  		if key == name {
  1173  			value, err := strconv.Unquote(qvalue)
  1174  			if err != nil {
  1175  				break
  1176  			}
  1177  			return value, true
  1178  		}
  1179  	}
  1180  	return "", false
  1181  }
  1182  
  1183  // Field returns the i'th struct field.
  1184  func (t *structType) Field(i int) (f StructField) {
  1185  	if i < 0 || i >= len(t.fields) {
  1186  		panic("reflect: Field index out of bounds")
  1187  	}
  1188  	p := &t.fields[i]
  1189  	f.Type = toType(p.typ)
  1190  	f.Name = p.name.name()
  1191  	f.Anonymous = p.embedded()
  1192  	if !p.name.isExported() {
  1193  		f.PkgPath = t.pkgPath.name()
  1194  	}
  1195  	if tag := p.name.tag(); tag != "" {
  1196  		f.Tag = StructTag(tag)
  1197  	}
  1198  	f.Offset = p.offset()
  1199  
  1200  	// NOTE(rsc): This is the only allocation in the interface
  1201  	// presented by a reflect.Type. It would be nice to avoid,
  1202  	// at least in the common cases, but we need to make sure
  1203  	// that misbehaving clients of reflect cannot affect other
  1204  	// uses of reflect. One possibility is CL 5371098, but we
  1205  	// postponed that ugliness until there is a demonstrated
  1206  	// need for the performance. This is issue 2320.
  1207  	f.Index = []int{i}
  1208  	return
  1209  }
  1210  
  1211  // TODO(gri): Should there be an error/bool indicator if the index
  1212  //            is wrong for FieldByIndex?
  1213  
  1214  // FieldByIndex returns the nested field corresponding to index.
  1215  func (t *structType) FieldByIndex(index []int) (f StructField) {
  1216  	f.Type = toType(&t.rtype)
  1217  	for i, x := range index {
  1218  		if i > 0 {
  1219  			ft := f.Type
  1220  			if ft.Kind() == Ptr && ft.Elem().Kind() == Struct {
  1221  				ft = ft.Elem()
  1222  			}
  1223  			f.Type = ft
  1224  		}
  1225  		f = f.Type.Field(x)
  1226  	}
  1227  	return
  1228  }
  1229  
  1230  // A fieldScan represents an item on the fieldByNameFunc scan work list.
  1231  type fieldScan struct {
  1232  	typ   *structType
  1233  	index []int
  1234  }
  1235  
  1236  // FieldByNameFunc returns the struct field with a name that satisfies the
  1237  // match function and a boolean to indicate if the field was found.
  1238  func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
  1239  	// This uses the same condition that the Go language does: there must be a unique instance
  1240  	// of the match at a given depth level. If there are multiple instances of a match at the
  1241  	// same depth, they annihilate each other and inhibit any possible match at a lower level.
  1242  	// The algorithm is breadth first search, one depth level at a time.
  1243  
  1244  	// The current and next slices are work queues:
  1245  	// current lists the fields to visit on this depth level,
  1246  	// and next lists the fields on the next lower level.
  1247  	current := []fieldScan{}
  1248  	next := []fieldScan{{typ: t}}
  1249  
  1250  	// nextCount records the number of times an embedded type has been
  1251  	// encountered and considered for queueing in the 'next' slice.
  1252  	// We only queue the first one, but we increment the count on each.
  1253  	// If a struct type T can be reached more than once at a given depth level,
  1254  	// then it annihilates itself and need not be considered at all when we
  1255  	// process that next depth level.
  1256  	var nextCount map[*structType]int
  1257  
  1258  	// visited records the structs that have been considered already.
  1259  	// Embedded pointer fields can create cycles in the graph of
  1260  	// reachable embedded types; visited avoids following those cycles.
  1261  	// It also avoids duplicated effort: if we didn't find the field in an
  1262  	// embedded type T at level 2, we won't find it in one at level 4 either.
  1263  	visited := map[*structType]bool{}
  1264  
  1265  	for len(next) > 0 {
  1266  		current, next = next, current[:0]
  1267  		count := nextCount
  1268  		nextCount = nil
  1269  
  1270  		// Process all the fields at this depth, now listed in 'current'.
  1271  		// The loop queues embedded fields found in 'next', for processing during the next
  1272  		// iteration. The multiplicity of the 'current' field counts is recorded
  1273  		// in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
  1274  		for _, scan := range current {
  1275  			t := scan.typ
  1276  			if visited[t] {
  1277  				// We've looked through this type before, at a higher level.
  1278  				// That higher level would shadow the lower level we're now at,
  1279  				// so this one can't be useful to us. Ignore it.
  1280  				continue
  1281  			}
  1282  			visited[t] = true
  1283  			for i := range t.fields {
  1284  				f := &t.fields[i]
  1285  				// Find name and (for embedded field) type for field f.
  1286  				fname := f.name.name()
  1287  				var ntyp *rtype
  1288  				if f.embedded() {
  1289  					// Embedded field of type T or *T.
  1290  					ntyp = f.typ
  1291  					if ntyp.Kind() == Ptr {
  1292  						ntyp = ntyp.Elem().common()
  1293  					}
  1294  				}
  1295  
  1296  				// Does it match?
  1297  				if match(fname) {
  1298  					// Potential match
  1299  					if count[t] > 1 || ok {
  1300  						// Name appeared multiple times at this level: annihilate.
  1301  						return StructField{}, false
  1302  					}
  1303  					result = t.Field(i)
  1304  					result.Index = nil
  1305  					result.Index = append(result.Index, scan.index...)
  1306  					result.Index = append(result.Index, i)
  1307  					ok = true
  1308  					continue
  1309  				}
  1310  
  1311  				// Queue embedded struct fields for processing with next level,
  1312  				// but only if we haven't seen a match yet at this level and only
  1313  				// if the embedded types haven't already been queued.
  1314  				if ok || ntyp == nil || ntyp.Kind() != Struct {
  1315  					continue
  1316  				}
  1317  				styp := (*structType)(unsafe.Pointer(ntyp))
  1318  				if nextCount[styp] > 0 {
  1319  					nextCount[styp] = 2 // exact multiple doesn't matter
  1320  					continue
  1321  				}
  1322  				if nextCount == nil {
  1323  					nextCount = map[*structType]int{}
  1324  				}
  1325  				nextCount[styp] = 1
  1326  				if count[t] > 1 {
  1327  					nextCount[styp] = 2 // exact multiple doesn't matter
  1328  				}
  1329  				var index []int
  1330  				index = append(index, scan.index...)
  1331  				index = append(index, i)
  1332  				next = append(next, fieldScan{styp, index})
  1333  			}
  1334  		}
  1335  		if ok {
  1336  			break
  1337  		}
  1338  	}
  1339  	return
  1340  }
  1341  
  1342  // FieldByName returns the struct field with the given name
  1343  // and a boolean to indicate if the field was found.
  1344  func (t *structType) FieldByName(name string) (f StructField, present bool) {
  1345  	// Quick check for top-level name, or struct without embedded fields.
  1346  	hasEmbeds := false
  1347  	if name != "" {
  1348  		for i := range t.fields {
  1349  			tf := &t.fields[i]
  1350  			if tf.name.name() == name {
  1351  				return t.Field(i), true
  1352  			}
  1353  			if tf.embedded() {
  1354  				hasEmbeds = true
  1355  			}
  1356  		}
  1357  	}
  1358  	if !hasEmbeds {
  1359  		return
  1360  	}
  1361  	return t.FieldByNameFunc(func(s string) bool { return s == name })
  1362  }
  1363  
  1364  // TypeOf returns the reflection Type that represents the dynamic type of i.
  1365  // If i is a nil interface value, TypeOf returns nil.
  1366  func TypeOf(i interface{}) Type {
  1367  	eface := *(*emptyInterface)(unsafe.Pointer(&i))
  1368  	return toType(eface.typ)
  1369  }
  1370  
  1371  // ptrMap is the cache for PtrTo.
  1372  var ptrMap sync.Map // map[*rtype]*ptrType
  1373  
  1374  // PtrTo returns the pointer type with element t.
  1375  // For example, if t represents type Foo, PtrTo(t) represents *Foo.
  1376  func PtrTo(t Type) Type {
  1377  	return t.(*rtype).ptrTo()
  1378  }
  1379  
  1380  func (t *rtype) ptrTo() *rtype {
  1381  	if t.ptrToThis != 0 {
  1382  		return t.typeOff(t.ptrToThis)
  1383  	}
  1384  
  1385  	// Check the cache.
  1386  	if pi, ok := ptrMap.Load(t); ok {
  1387  		return &pi.(*ptrType).rtype
  1388  	}
  1389  
  1390  	// Look in known types.
  1391  	s := "*" + t.String()
  1392  	for _, tt := range typesByString(s) {
  1393  		p := (*ptrType)(unsafe.Pointer(tt))
  1394  		if p.elem != t {
  1395  			continue
  1396  		}
  1397  		pi, _ := ptrMap.LoadOrStore(t, p)
  1398  		return &pi.(*ptrType).rtype
  1399  	}
  1400  
  1401  	// Create a new ptrType starting with the description
  1402  	// of an *unsafe.Pointer.
  1403  	var iptr interface{} = (*unsafe.Pointer)(nil)
  1404  	prototype := *(**ptrType)(unsafe.Pointer(&iptr))
  1405  	pp := *prototype
  1406  
  1407  	pp.str = resolveReflectName(newName(s, "", false))
  1408  	pp.ptrToThis = 0
  1409  
  1410  	// For the type structures linked into the binary, the
  1411  	// compiler provides a good hash of the string.
  1412  	// Create a good hash for the new string by using
  1413  	// the FNV-1 hash's mixing function to combine the
  1414  	// old hash and the new "*".
  1415  	pp.hash = fnv1(t.hash, '*')
  1416  
  1417  	pp.elem = t
  1418  
  1419  	pi, _ := ptrMap.LoadOrStore(t, &pp)
  1420  	return &pi.(*ptrType).rtype
  1421  }
  1422  
  1423  // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
  1424  func fnv1(x uint32, list ...byte) uint32 {
  1425  	for _, b := range list {
  1426  		x = x*16777619 ^ uint32(b)
  1427  	}
  1428  	return x
  1429  }
  1430  
  1431  func (t *rtype) Implements(u Type) bool {
  1432  	if u == nil {
  1433  		panic("reflect: nil type passed to Type.Implements")
  1434  	}
  1435  	if u.Kind() != Interface {
  1436  		panic("reflect: non-interface type passed to Type.Implements")
  1437  	}
  1438  	return implements(u.(*rtype), t)
  1439  }
  1440  
  1441  func (t *rtype) AssignableTo(u Type) bool {
  1442  	if u == nil {
  1443  		panic("reflect: nil type passed to Type.AssignableTo")
  1444  	}
  1445  	uu := u.(*rtype)
  1446  	return directlyAssignable(uu, t) || implements(uu, t)
  1447  }
  1448  
  1449  func (t *rtype) ConvertibleTo(u Type) bool {
  1450  	if u == nil {
  1451  		panic("reflect: nil type passed to Type.ConvertibleTo")
  1452  	}
  1453  	uu := u.(*rtype)
  1454  	return convertOp(uu, t) != nil
  1455  }
  1456  
  1457  func (t *rtype) Comparable() bool {
  1458  	return t.equal != nil
  1459  }
  1460  
  1461  // implements reports whether the type V implements the interface type T.
  1462  func implements(T, V *rtype) bool {
  1463  	if T.Kind() != Interface {
  1464  		return false
  1465  	}
  1466  	t := (*interfaceType)(unsafe.Pointer(T))
  1467  	if len(t.methods) == 0 {
  1468  		return true
  1469  	}
  1470  
  1471  	// The same algorithm applies in both cases, but the
  1472  	// method tables for an interface type and a concrete type
  1473  	// are different, so the code is duplicated.
  1474  	// In both cases the algorithm is a linear scan over the two
  1475  	// lists - T's methods and V's methods - simultaneously.
  1476  	// Since method tables are stored in a unique sorted order
  1477  	// (alphabetical, with no duplicate method names), the scan
  1478  	// through V's methods must hit a match for each of T's
  1479  	// methods along the way, or else V does not implement T.
  1480  	// This lets us run the scan in overall linear time instead of
  1481  	// the quadratic time  a naive search would require.
  1482  	// See also ../runtime/iface.go.
  1483  	if V.Kind() == Interface {
  1484  		v := (*interfaceType)(unsafe.Pointer(V))
  1485  		i := 0
  1486  		for j := 0; j < len(v.methods); j++ {
  1487  			tm := &t.methods[i]
  1488  			tmName := t.nameOff(tm.name)
  1489  			vm := &v.methods[j]
  1490  			vmName := V.nameOff(vm.name)
  1491  			if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
  1492  				if !tmName.isExported() {
  1493  					tmPkgPath := tmName.pkgPath()
  1494  					if tmPkgPath == "" {
  1495  						tmPkgPath = t.pkgPath.name()
  1496  					}
  1497  					vmPkgPath := vmName.pkgPath()
  1498  					if vmPkgPath == "" {
  1499  						vmPkgPath = v.pkgPath.name()
  1500  					}
  1501  					if tmPkgPath != vmPkgPath {
  1502  						continue
  1503  					}
  1504  				}
  1505  				if i++; i >= len(t.methods) {
  1506  					return true
  1507  				}
  1508  			}
  1509  		}
  1510  		return false
  1511  	}
  1512  
  1513  	v := V.uncommon()
  1514  	if v == nil {
  1515  		return false
  1516  	}
  1517  	i := 0
  1518  	vmethods := v.methods()
  1519  	for j := 0; j < int(v.mcount); j++ {
  1520  		tm := &t.methods[i]
  1521  		tmName := t.nameOff(tm.name)
  1522  		vm := vmethods[j]
  1523  		vmName := V.nameOff(vm.name)
  1524  		if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
  1525  			if !tmName.isExported() {
  1526  				tmPkgPath := tmName.pkgPath()
  1527  				if tmPkgPath == "" {
  1528  					tmPkgPath = t.pkgPath.name()
  1529  				}
  1530  				vmPkgPath := vmName.pkgPath()
  1531  				if vmPkgPath == "" {
  1532  					vmPkgPath = V.nameOff(v.pkgPath).name()
  1533  				}
  1534  				if tmPkgPath != vmPkgPath {
  1535  					continue
  1536  				}
  1537  			}
  1538  			if i++; i >= len(t.methods) {
  1539  				return true
  1540  			}
  1541  		}
  1542  	}
  1543  	return false
  1544  }
  1545  
  1546  // specialChannelAssignability reports whether a value x of channel type V
  1547  // can be directly assigned (using memmove) to another channel type T.
  1548  // https://golang.org/doc/go_spec.html#Assignability
  1549  // T and V must be both of Chan kind.
  1550  func specialChannelAssignability(T, V *rtype) bool {
  1551  	// Special case:
  1552  	// x is a bidirectional channel value, T is a channel type,
  1553  	// x's type V and T have identical element types,
  1554  	// and at least one of V or T is not a defined type.
  1555  	return V.ChanDir() == BothDir && (T.Name() == "" || V.Name() == "") && haveIdenticalType(T.Elem(), V.Elem(), true)
  1556  }
  1557  
  1558  // directlyAssignable reports whether a value x of type V can be directly
  1559  // assigned (using memmove) to a value of type T.
  1560  // https://golang.org/doc/go_spec.html#Assignability
  1561  // Ignoring the interface rules (implemented elsewhere)
  1562  // and the ideal constant rules (no ideal constants at run time).
  1563  func directlyAssignable(T, V *rtype) bool {
  1564  	// x's type V is identical to T?
  1565  	if T == V {
  1566  		return true
  1567  	}
  1568  
  1569  	// Otherwise at least one of T and V must not be defined
  1570  	// and they must have the same kind.
  1571  	if T.hasName() && V.hasName() || T.Kind() != V.Kind() {
  1572  		return false
  1573  	}
  1574  
  1575  	if T.Kind() == Chan && specialChannelAssignability(T, V) {
  1576  		return true
  1577  	}
  1578  
  1579  	// x's type T and V must have identical underlying types.
  1580  	return haveIdenticalUnderlyingType(T, V, true)
  1581  }
  1582  
  1583  func haveIdenticalType(T, V Type, cmpTags bool) bool {
  1584  	if cmpTags {
  1585  		return T == V
  1586  	}
  1587  
  1588  	if T.Name() != V.Name() || T.Kind() != V.Kind() {
  1589  		return false
  1590  	}
  1591  
  1592  	return haveIdenticalUnderlyingType(T.common(), V.common(), false)
  1593  }
  1594  
  1595  func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
  1596  	if T == V {
  1597  		return true
  1598  	}
  1599  
  1600  	kind := T.Kind()
  1601  	if kind != V.Kind() {
  1602  		return false
  1603  	}
  1604  
  1605  	// Non-composite types of equal kind have same underlying type
  1606  	// (the predefined instance of the type).
  1607  	if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
  1608  		return true
  1609  	}
  1610  
  1611  	// Composite types.
  1612  	switch kind {
  1613  	case Array:
  1614  		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
  1615  
  1616  	case Chan:
  1617  		return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
  1618  
  1619  	case Func:
  1620  		t := (*funcType)(unsafe.Pointer(T))
  1621  		v := (*funcType)(unsafe.Pointer(V))
  1622  		if t.outCount != v.outCount || t.inCount != v.inCount {
  1623  			return false
  1624  		}
  1625  		for i := 0; i < t.NumIn(); i++ {
  1626  			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
  1627  				return false
  1628  			}
  1629  		}
  1630  		for i := 0; i < t.NumOut(); i++ {
  1631  			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
  1632  				return false
  1633  			}
  1634  		}
  1635  		return true
  1636  
  1637  	case Interface:
  1638  		t := (*interfaceType)(unsafe.Pointer(T))
  1639  		v := (*interfaceType)(unsafe.Pointer(V))
  1640  		if len(t.methods) == 0 && len(v.methods) == 0 {
  1641  			return true
  1642  		}
  1643  		// Might have the same methods but still
  1644  		// need a run time conversion.
  1645  		return false
  1646  
  1647  	case Map:
  1648  		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
  1649  
  1650  	case Ptr, Slice:
  1651  		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
  1652  
  1653  	case Struct:
  1654  		t := (*structType)(unsafe.Pointer(T))
  1655  		v := (*structType)(unsafe.Pointer(V))
  1656  		if len(t.fields) != len(v.fields) {
  1657  			return false
  1658  		}
  1659  		if t.pkgPath.name() != v.pkgPath.name() {
  1660  			return false
  1661  		}
  1662  		for i := range t.fields {
  1663  			tf := &t.fields[i]
  1664  			vf := &v.fields[i]
  1665  			if tf.name.name() != vf.name.name() {
  1666  				return false
  1667  			}
  1668  			if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
  1669  				return false
  1670  			}
  1671  			if cmpTags && tf.name.tag() != vf.name.tag() {
  1672  				return false
  1673  			}
  1674  			if tf.offsetEmbed != vf.offsetEmbed {
  1675  				return false
  1676  			}
  1677  		}
  1678  		return true
  1679  	}
  1680  
  1681  	return false
  1682  }
  1683  
  1684  // typelinks is implemented in package runtime.
  1685  // It returns a slice of the sections in each module,
  1686  // and a slice of *rtype offsets in each module.
  1687  //
  1688  // The types in each module are sorted by string. That is, the first
  1689  // two linked types of the first module are:
  1690  //
  1691  //	d0 := sections[0]
  1692  //	t1 := (*rtype)(add(d0, offset[0][0]))
  1693  //	t2 := (*rtype)(add(d0, offset[0][1]))
  1694  //
  1695  // and
  1696  //
  1697  //	t1.String() < t2.String()
  1698  //
  1699  // Note that strings are not unique identifiers for types:
  1700  // there can be more than one with a given string.
  1701  // Only types we might want to look up are included:
  1702  // pointers, channels, maps, slices, and arrays.
  1703  func typelinks() (sections []unsafe.Pointer, offset [][]int32)
  1704  
  1705  func rtypeOff(section unsafe.Pointer, off int32) *rtype {
  1706  	return (*rtype)(add(section, uintptr(off), "sizeof(rtype) > 0"))
  1707  }
  1708  
  1709  // typesByString returns the subslice of typelinks() whose elements have
  1710  // the given string representation.
  1711  // It may be empty (no known types with that string) or may have
  1712  // multiple elements (multiple types with that string).
  1713  func typesByString(s string) []*rtype {
  1714  	sections, offset := typelinks()
  1715  	var ret []*rtype
  1716  
  1717  	for offsI, offs := range offset {
  1718  		section := sections[offsI]
  1719  
  1720  		// We are looking for the first index i where the string becomes >= s.
  1721  		// This is a copy of sort.Search, with f(h) replaced by (*typ[h].String() >= s).
  1722  		i, j := 0, len(offs)
  1723  		for i < j {
  1724  			h := i + (j-i)/2 // avoid overflow when computing h
  1725  			// i ≤ h < j
  1726  			if !(rtypeOff(section, offs[h]).String() >= s) {
  1727  				i = h + 1 // preserves f(i-1) == false
  1728  			} else {
  1729  				j = h // preserves f(j) == true
  1730  			}
  1731  		}
  1732  		// i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
  1733  
  1734  		// Having found the first, linear scan forward to find the last.
  1735  		// We could do a second binary search, but the caller is going
  1736  		// to do a linear scan anyway.
  1737  		for j := i; j < len(offs); j++ {
  1738  			typ := rtypeOff(section, offs[j])
  1739  			if typ.String() != s {
  1740  				break
  1741  			}
  1742  			ret = append(ret, typ)
  1743  		}
  1744  	}
  1745  	return ret
  1746  }
  1747  
  1748  // The lookupCache caches ArrayOf, ChanOf, MapOf and SliceOf lookups.
  1749  var lookupCache sync.Map // map[cacheKey]*rtype
  1750  
  1751  // A cacheKey is the key for use in the lookupCache.
  1752  // Four values describe any of the types we are looking for:
  1753  // type kind, one or two subtypes, and an extra integer.
  1754  type cacheKey struct {
  1755  	kind  Kind
  1756  	t1    *rtype
  1757  	t2    *rtype
  1758  	extra uintptr
  1759  }
  1760  
  1761  // The funcLookupCache caches FuncOf lookups.
  1762  // FuncOf does not share the common lookupCache since cacheKey is not
  1763  // sufficient to represent functions unambiguously.
  1764  var funcLookupCache struct {
  1765  	sync.Mutex // Guards stores (but not loads) on m.
  1766  
  1767  	// m is a map[uint32][]*rtype keyed by the hash calculated in FuncOf.
  1768  	// Elements of m are append-only and thus safe for concurrent reading.
  1769  	m sync.Map
  1770  }
  1771  
  1772  // ChanOf returns the channel type with the given direction and element type.
  1773  // For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
  1774  //
  1775  // The gc runtime imposes a limit of 64 kB on channel element types.
  1776  // If t's size is equal to or exceeds this limit, ChanOf panics.
  1777  func ChanOf(dir ChanDir, t Type) Type {
  1778  	typ := t.(*rtype)
  1779  
  1780  	// Look in cache.
  1781  	ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
  1782  	if ch, ok := lookupCache.Load(ckey); ok {
  1783  		return ch.(*rtype)
  1784  	}
  1785  
  1786  	// This restriction is imposed by the gc compiler and the runtime.
  1787  	if typ.size >= 1<<16 {
  1788  		panic("reflect.ChanOf: element size too large")
  1789  	}
  1790  
  1791  	// Look in known types.
  1792  	// TODO: Precedence when constructing string.
  1793  	var s string
  1794  	switch dir {
  1795  	default:
  1796  		panic("reflect.ChanOf: invalid dir")
  1797  	case SendDir:
  1798  		s = "chan<- " + typ.String()
  1799  	case RecvDir:
  1800  		s = "<-chan " + typ.String()
  1801  	case BothDir:
  1802  		s = "chan " + typ.String()
  1803  	}
  1804  	for _, tt := range typesByString(s) {
  1805  		ch := (*chanType)(unsafe.Pointer(tt))
  1806  		if ch.elem == typ && ch.dir == uintptr(dir) {
  1807  			ti, _ := lookupCache.LoadOrStore(ckey, tt)
  1808  			return ti.(Type)
  1809  		}
  1810  	}
  1811  
  1812  	// Make a channel type.
  1813  	var ichan interface{} = (chan unsafe.Pointer)(nil)
  1814  	prototype := *(**chanType)(unsafe.Pointer(&ichan))
  1815  	ch := *prototype
  1816  	ch.tflag = tflagRegularMemory
  1817  	ch.dir = uintptr(dir)
  1818  	ch.str = resolveReflectName(newName(s, "", false))
  1819  	ch.hash = fnv1(typ.hash, 'c', byte(dir))
  1820  	ch.elem = typ
  1821  
  1822  	ti, _ := lookupCache.LoadOrStore(ckey, &ch.rtype)
  1823  	return ti.(Type)
  1824  }
  1825  
  1826  // MapOf returns the map type with the given key and element types.
  1827  // For example, if k represents int and e represents string,
  1828  // MapOf(k, e) represents map[int]string.
  1829  //
  1830  // If the key type is not a valid map key type (that is, if it does
  1831  // not implement Go's == operator), MapOf panics.
  1832  func MapOf(key, elem Type) Type {
  1833  	ktyp := key.(*rtype)
  1834  	etyp := elem.(*rtype)
  1835  
  1836  	if ktyp.equal == nil {
  1837  		panic("reflect.MapOf: invalid key type " + ktyp.String())
  1838  	}
  1839  
  1840  	// Look in cache.
  1841  	ckey := cacheKey{Map, ktyp, etyp, 0}
  1842  	if mt, ok := lookupCache.Load(ckey); ok {
  1843  		return mt.(Type)
  1844  	}
  1845  
  1846  	// Look in known types.
  1847  	s := "map[" + ktyp.String() + "]" + etyp.String()
  1848  	for _, tt := range typesByString(s) {
  1849  		mt := (*mapType)(unsafe.Pointer(tt))
  1850  		if mt.key == ktyp && mt.elem == etyp {
  1851  			ti, _ := lookupCache.LoadOrStore(ckey, tt)
  1852  			return ti.(Type)
  1853  		}
  1854  	}
  1855  
  1856  	// Make a map type.
  1857  	// Note: flag values must match those used in the TMAP case
  1858  	// in ../cmd/compile/internal/gc/reflect.go:dtypesym.
  1859  	var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
  1860  	mt := **(**mapType)(unsafe.Pointer(&imap))
  1861  	mt.str = resolveReflectName(newName(s, "", false))
  1862  	mt.tflag = 0
  1863  	mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
  1864  	mt.key = ktyp
  1865  	mt.elem = etyp
  1866  	mt.bucket = bucketOf(ktyp, etyp)
  1867  	mt.hasher = func(p unsafe.Pointer, seed uintptr) uintptr {
  1868  		return typehash(ktyp, p, seed)
  1869  	}
  1870  	mt.flags = 0
  1871  	if ktyp.size > maxKeySize {
  1872  		mt.keysize = uint8(ptrSize)
  1873  		mt.flags |= 1 // indirect key
  1874  	} else {
  1875  		mt.keysize = uint8(ktyp.size)
  1876  	}
  1877  	if etyp.size > maxValSize {
  1878  		mt.valuesize = uint8(ptrSize)
  1879  		mt.flags |= 2 // indirect value
  1880  	} else {
  1881  		mt.valuesize = uint8(etyp.size)
  1882  	}
  1883  	mt.bucketsize = uint16(mt.bucket.size)
  1884  	if isReflexive(ktyp) {
  1885  		mt.flags |= 4
  1886  	}
  1887  	if needKeyUpdate(ktyp) {
  1888  		mt.flags |= 8
  1889  	}
  1890  	if hashMightPanic(ktyp) {
  1891  		mt.flags |= 16
  1892  	}
  1893  	mt.ptrToThis = 0
  1894  
  1895  	ti, _ := lookupCache.LoadOrStore(ckey, &mt.rtype)
  1896  	return ti.(Type)
  1897  }
  1898  
  1899  // TODO(crawshaw): as these funcTypeFixedN structs have no methods,
  1900  // they could be defined at runtime using the StructOf function.
  1901  type funcTypeFixed4 struct {
  1902  	funcType
  1903  	args [4]*rtype
  1904  }
  1905  type funcTypeFixed8 struct {
  1906  	funcType
  1907  	args [8]*rtype
  1908  }
  1909  type funcTypeFixed16 struct {
  1910  	funcType
  1911  	args [16]*rtype
  1912  }
  1913  type funcTypeFixed32 struct {
  1914  	funcType
  1915  	args [32]*rtype
  1916  }
  1917  type funcTypeFixed64 struct {
  1918  	funcType
  1919  	args [64]*rtype
  1920  }
  1921  type funcTypeFixed128 struct {
  1922  	funcType
  1923  	args [128]*rtype
  1924  }
  1925  
  1926  // FuncOf returns the function type with the given argument and result types.
  1927  // For example if k represents int and e represents string,
  1928  // FuncOf([]Type{k}, []Type{e}, false) represents func(int) string.
  1929  //
  1930  // The variadic argument controls whether the function is variadic. FuncOf
  1931  // panics if the in[len(in)-1] does not represent a slice and variadic is
  1932  // true.
  1933  func FuncOf(in, out []Type, variadic bool) Type {
  1934  	if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) {
  1935  		panic("reflect.FuncOf: last arg of variadic func must be slice")
  1936  	}
  1937  
  1938  	// Make a func type.
  1939  	var ifunc interface{} = (func())(nil)
  1940  	prototype := *(**funcType)(unsafe.Pointer(&ifunc))
  1941  	n := len(in) + len(out)
  1942  
  1943  	var ft *funcType
  1944  	var args []*rtype
  1945  	switch {
  1946  	case n <= 4:
  1947  		fixed := new(funcTypeFixed4)
  1948  		args = fixed.args[:0:len(fixed.args)]
  1949  		ft = &fixed.funcType
  1950  	case n <= 8:
  1951  		fixed := new(funcTypeFixed8)
  1952  		args = fixed.args[:0:len(fixed.args)]
  1953  		ft = &fixed.funcType
  1954  	case n <= 16:
  1955  		fixed := new(funcTypeFixed16)
  1956  		args = fixed.args[:0:len(fixed.args)]
  1957  		ft = &fixed.funcType
  1958  	case n <= 32:
  1959  		fixed := new(funcTypeFixed32)
  1960  		args = fixed.args[:0:len(fixed.args)]
  1961  		ft = &fixed.funcType
  1962  	case n <= 64:
  1963  		fixed := new(funcTypeFixed64)
  1964  		args = fixed.args[:0:len(fixed.args)]
  1965  		ft = &fixed.funcType
  1966  	case n <= 128:
  1967  		fixed := new(funcTypeFixed128)
  1968  		args = fixed.args[:0:len(fixed.args)]
  1969  		ft = &fixed.funcType
  1970  	default:
  1971  		panic("reflect.FuncOf: too many arguments")
  1972  	}
  1973  	*ft = *prototype
  1974  
  1975  	// Build a hash and minimally populate ft.
  1976  	var hash uint32
  1977  	for _, in := range in {
  1978  		t := in.(*rtype)
  1979  		args = append(args, t)
  1980  		hash = fnv1(hash, byte(t.hash>>24), byte(t.hash>>16), byte(t.hash>>8), byte(t.hash))
  1981  	}
  1982  	if variadic {
  1983  		hash = fnv1(hash, 'v')
  1984  	}
  1985  	hash = fnv1(hash, '.')
  1986  	for _, out := range out {
  1987  		t := out.(*rtype)
  1988  		args = append(args, t)
  1989  		hash = fnv1(hash, byte(t.hash>>24), byte(t.hash>>16), byte(t.hash>>8), byte(t.hash))
  1990  	}
  1991  	if len(args) > 50 {
  1992  		panic("reflect.FuncOf does not support more than 50 arguments")
  1993  	}
  1994  	ft.tflag = 0
  1995  	ft.hash = hash
  1996  	ft.inCount = uint16(len(in))
  1997  	ft.outCount = uint16(len(out))
  1998  	if variadic {
  1999  		ft.outCount |= 1 << 15
  2000  	}
  2001  
  2002  	// Look in cache.
  2003  	if ts, ok := funcLookupCache.m.Load(hash); ok {
  2004  		for _, t := range ts.([]*rtype) {
  2005  			if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
  2006  				return t
  2007  			}
  2008  		}
  2009  	}
  2010  
  2011  	// Not in cache, lock and retry.
  2012  	funcLookupCache.Lock()
  2013  	defer funcLookupCache.Unlock()
  2014  	if ts, ok := funcLookupCache.m.Load(hash); ok {
  2015  		for _, t := range ts.([]*rtype) {
  2016  			if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
  2017  				return t
  2018  			}
  2019  		}
  2020  	}
  2021  
  2022  	addToCache := func(tt *rtype) Type {
  2023  		var rts []*rtype
  2024  		if rti, ok := funcLookupCache.m.Load(hash); ok {
  2025  			rts = rti.([]*rtype)
  2026  		}
  2027  		funcLookupCache.m.Store(hash, append(rts, tt))
  2028  		return tt
  2029  	}
  2030  
  2031  	// Look in known types for the same string representation.
  2032  	str := funcStr(ft)
  2033  	for _, tt := range typesByString(str) {
  2034  		if haveIdenticalUnderlyingType(&ft.rtype, tt, true) {
  2035  			return addToCache(tt)
  2036  		}
  2037  	}
  2038  
  2039  	// Populate the remaining fields of ft and store in cache.
  2040  	ft.str = resolveReflectName(newName(str, "", false))
  2041  	ft.ptrToThis = 0
  2042  	return addToCache(&ft.rtype)
  2043  }
  2044  
  2045  // funcStr builds a string representation of a funcType.
  2046  func funcStr(ft *funcType) string {
  2047  	repr := make([]byte, 0, 64)
  2048  	repr = append(repr, "func("...)
  2049  	for i, t := range ft.in() {
  2050  		if i > 0 {
  2051  			repr = append(repr, ", "...)
  2052  		}
  2053  		if ft.IsVariadic() && i == int(ft.inCount)-1 {
  2054  			repr = append(repr, "..."...)
  2055  			repr = append(repr, (*sliceType)(unsafe.Pointer(t)).elem.String()...)
  2056  		} else {
  2057  			repr = append(repr, t.String()...)
  2058  		}
  2059  	}
  2060  	repr = append(repr, ')')
  2061  	out := ft.out()
  2062  	if len(out) == 1 {
  2063  		repr = append(repr, ' ')
  2064  	} else if len(out) > 1 {
  2065  		repr = append(repr, " ("...)
  2066  	}
  2067  	for i, t := range out {
  2068  		if i > 0 {
  2069  			repr = append(repr, ", "...)
  2070  		}
  2071  		repr = append(repr, t.String()...)
  2072  	}
  2073  	if len(out) > 1 {
  2074  		repr = append(repr, ')')
  2075  	}
  2076  	return string(repr)
  2077  }
  2078  
  2079  // isReflexive reports whether the == operation on the type is reflexive.
  2080  // That is, x == x for all values x of type t.
  2081  func isReflexive(t *rtype) bool {
  2082  	switch t.Kind() {
  2083  	case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, String, UnsafePointer:
  2084  		return true
  2085  	case Float32, Float64, Complex64, Complex128, Interface:
  2086  		return false
  2087  	case Array:
  2088  		tt := (*arrayType)(unsafe.Pointer(t))
  2089  		return isReflexive(tt.elem)
  2090  	case Struct:
  2091  		tt := (*structType)(unsafe.Pointer(t))
  2092  		for _, f := range tt.fields {
  2093  			if !isReflexive(f.typ) {
  2094  				return false
  2095  			}
  2096  		}
  2097  		return true
  2098  	default:
  2099  		// Func, Map, Slice, Invalid
  2100  		panic("isReflexive called on non-key type " + t.String())
  2101  	}
  2102  }
  2103  
  2104  // needKeyUpdate reports whether map overwrites require the key to be copied.
  2105  func needKeyUpdate(t *rtype) bool {
  2106  	switch t.Kind() {
  2107  	case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, UnsafePointer:
  2108  		return false
  2109  	case Float32, Float64, Complex64, Complex128, Interface, String:
  2110  		// Float keys can be updated from +0 to -0.
  2111  		// String keys can be updated to use a smaller backing store.
  2112  		// Interfaces might have floats of strings in them.
  2113  		return true
  2114  	case Array:
  2115  		tt := (*arrayType)(unsafe.Pointer(t))
  2116  		return needKeyUpdate(tt.elem)
  2117  	case Struct:
  2118  		tt := (*structType)(unsafe.Pointer(t))
  2119  		for _, f := range tt.fields {
  2120  			if needKeyUpdate(f.typ) {
  2121  				return true
  2122  			}
  2123  		}
  2124  		return false
  2125  	default:
  2126  		// Func, Map, Slice, Invalid
  2127  		panic("needKeyUpdate called on non-key type " + t.String())
  2128  	}
  2129  }
  2130  
  2131  // hashMightPanic reports whether the hash of a map key of type t might panic.
  2132  func hashMightPanic(t *rtype) bool {
  2133  	switch t.Kind() {
  2134  	case Interface:
  2135  		return true
  2136  	case Array:
  2137  		tt := (*arrayType)(unsafe.Pointer(t))
  2138  		return hashMightPanic(tt.elem)
  2139  	case Struct:
  2140  		tt := (*structType)(unsafe.Pointer(t))
  2141  		for _, f := range tt.fields {
  2142  			if hashMightPanic(f.typ) {
  2143  				return true
  2144  			}
  2145  		}
  2146  		return false
  2147  	default:
  2148  		return false
  2149  	}
  2150  }
  2151  
  2152  // Make sure these routines stay in sync with ../../runtime/map.go!
  2153  // These types exist only for GC, so we only fill out GC relevant info.
  2154  // Currently, that's just size and the GC program. We also fill in string
  2155  // for possible debugging use.
  2156  const (
  2157  	bucketSize uintptr = 8
  2158  	maxKeySize uintptr = 128
  2159  	maxValSize uintptr = 128
  2160  )
  2161  
  2162  func bucketOf(ktyp, etyp *rtype) *rtype {
  2163  	if ktyp.size > maxKeySize {
  2164  		ktyp = PtrTo(ktyp).(*rtype)
  2165  	}
  2166  	if etyp.size > maxValSize {
  2167  		etyp = PtrTo(etyp).(*rtype)
  2168  	}
  2169  
  2170  	// Prepare GC data if any.
  2171  	// A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+2*ptrSize bytes,
  2172  	// or 2072 bytes, or 259 pointer-size words, or 33 bytes of pointer bitmap.
  2173  	// Note that since the key and value are known to be <= 128 bytes,
  2174  	// they're guaranteed to have bitmaps instead of GC programs.
  2175  	var gcdata *byte
  2176  	var ptrdata uintptr
  2177  	var overflowPad uintptr
  2178  
  2179  	size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + ptrSize
  2180  	if size&uintptr(ktyp.align-1) != 0 || size&uintptr(etyp.align-1) != 0 {
  2181  		panic("reflect: bad size computation in MapOf")
  2182  	}
  2183  
  2184  	if ktyp.ptrdata != 0 || etyp.ptrdata != 0 {
  2185  		nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize
  2186  		mask := make([]byte, (nptr+7)/8)
  2187  		base := bucketSize / ptrSize
  2188  
  2189  		if ktyp.ptrdata != 0 {
  2190  			emitGCMask(mask, base, ktyp, bucketSize)
  2191  		}
  2192  		base += bucketSize * ktyp.size / ptrSize
  2193  
  2194  		if etyp.ptrdata != 0 {
  2195  			emitGCMask(mask, base, etyp, bucketSize)
  2196  		}
  2197  		base += bucketSize * etyp.size / ptrSize
  2198  		base += overflowPad / ptrSize
  2199  
  2200  		word := base
  2201  		mask[word/8] |= 1 << (word % 8)
  2202  		gcdata = &mask[0]
  2203  		ptrdata = (word + 1) * ptrSize
  2204  
  2205  		// overflow word must be last
  2206  		if ptrdata != size {
  2207  			panic("reflect: bad layout computation in MapOf")
  2208  		}
  2209  	}
  2210  
  2211  	b := &rtype{
  2212  		align:   ptrSize,
  2213  		size:    size,
  2214  		kind:    uint8(Struct),
  2215  		ptrdata: ptrdata,
  2216  		gcdata:  gcdata,
  2217  	}
  2218  	if overflowPad > 0 {
  2219  		b.align = 8
  2220  	}
  2221  	s := "bucket(" + ktyp.String() + "," + etyp.String() + ")"
  2222  	b.str = resolveReflectName(newName(s, "", false))
  2223  	return b
  2224  }
  2225  
  2226  func (t *rtype) gcSlice(begin, end uintptr) []byte {
  2227  	return (*[1 << 30]byte)(unsafe.Pointer(t.gcdata))[begin:end:end]
  2228  }
  2229  
  2230  // emitGCMask writes the GC mask for [n]typ into out, starting at bit
  2231  // offset base.
  2232  func emitGCMask(out []byte, base uintptr, typ *rtype, n uintptr) {
  2233  	if typ.kind&kindGCProg != 0 {
  2234  		panic("reflect: unexpected GC program")
  2235  	}
  2236  	ptrs := typ.ptrdata / ptrSize
  2237  	words := typ.size / ptrSize
  2238  	mask := typ.gcSlice(0, (ptrs+7)/8)
  2239  	for j := uintptr(0); j < ptrs; j++ {
  2240  		if (mask[j/8]>>(j%8))&1 != 0 {
  2241  			for i := uintptr(0); i < n; i++ {
  2242  				k := base + i*words + j
  2243  				out[k/8] |= 1 << (k % 8)
  2244  			}
  2245  		}
  2246  	}
  2247  }
  2248  
  2249  // appendGCProg appends the GC program for the first ptrdata bytes of
  2250  // typ to dst and returns the extended slice.
  2251  func appendGCProg(dst []byte, typ *rtype) []byte {
  2252  	if typ.kind&kindGCProg != 0 {
  2253  		// Element has GC program; emit one element.
  2254  		n := uintptr(*(*uint32)(unsafe.Pointer(typ.gcdata)))
  2255  		prog := typ.gcSlice(4, 4+n-1)
  2256  		return append(dst, prog...)
  2257  	}
  2258  
  2259  	// Element is small with pointer mask; use as literal bits.
  2260  	ptrs := typ.ptrdata / ptrSize
  2261  	mask := typ.gcSlice(0, (ptrs+7)/8)
  2262  
  2263  	// Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes).
  2264  	for ; ptrs > 120; ptrs -= 120 {
  2265  		dst = append(dst, 120)
  2266  		dst = append(dst, mask[:15]...)
  2267  		mask = mask[15:]
  2268  	}
  2269  
  2270  	dst = append(dst, byte(ptrs))
  2271  	dst = append(dst, mask...)
  2272  	return dst
  2273  }
  2274  
  2275  // SliceOf returns the slice type with element type t.
  2276  // For example, if t represents int, SliceOf(t) represents []int.
  2277  func SliceOf(t Type) Type {
  2278  	typ := t.(*rtype)
  2279  
  2280  	// Look in cache.
  2281  	ckey := cacheKey{Slice, typ, nil, 0}
  2282  	if slice, ok := lookupCache.Load(ckey); ok {
  2283  		return slice.(Type)
  2284  	}
  2285  
  2286  	// Look in known types.
  2287  	s := "[]" + typ.String()
  2288  	for _, tt := range typesByString(s) {
  2289  		slice := (*sliceType)(unsafe.Pointer(tt))
  2290  		if slice.elem == typ {
  2291  			ti, _ := lookupCache.LoadOrStore(ckey, tt)
  2292  			return ti.(Type)
  2293  		}
  2294  	}
  2295  
  2296  	// Make a slice type.
  2297  	var islice interface{} = ([]unsafe.Pointer)(nil)
  2298  	prototype := *(**sliceType)(unsafe.Pointer(&islice))
  2299  	slice := *prototype
  2300  	slice.tflag = 0
  2301  	slice.str = resolveReflectName(newName(s, "", false))
  2302  	slice.hash = fnv1(typ.hash, '[')
  2303  	slice.elem = typ
  2304  	slice.ptrToThis = 0
  2305  
  2306  	ti, _ := lookupCache.LoadOrStore(ckey, &slice.rtype)
  2307  	return ti.(Type)
  2308  }
  2309  
  2310  // The structLookupCache caches StructOf lookups.
  2311  // StructOf does not share the common lookupCache since we need to pin
  2312  // the memory associated with *structTypeFixedN.
  2313  var structLookupCache struct {
  2314  	sync.Mutex // Guards stores (but not loads) on m.
  2315  
  2316  	// m is a map[uint32][]Type keyed by the hash calculated in StructOf.
  2317  	// Elements in m are append-only and thus safe for concurrent reading.
  2318  	m sync.Map
  2319  }
  2320  
  2321  type structTypeUncommon struct {
  2322  	structType
  2323  	u uncommonType
  2324  }
  2325  
  2326  // isLetter reports whether a given 'rune' is classified as a Letter.
  2327  func isLetter(ch rune) bool {
  2328  	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
  2329  }
  2330  
  2331  // isValidFieldName checks if a string is a valid (struct) field name or not.
  2332  //
  2333  // According to the language spec, a field name should be an identifier.
  2334  //
  2335  // identifier = letter { letter | unicode_digit } .
  2336  // letter = unicode_letter | "_" .
  2337  func isValidFieldName(fieldName string) bool {
  2338  	for i, c := range fieldName {
  2339  		if i == 0 && !isLetter(c) {
  2340  			return false
  2341  		}
  2342  
  2343  		if !(isLetter(c) || unicode.IsDigit(c)) {
  2344  			return false
  2345  		}
  2346  	}
  2347  
  2348  	return len(fieldName) > 0
  2349  }
  2350  
  2351  // StructOf returns the struct type containing fields.
  2352  // The Offset and Index fields are ignored and computed as they would be
  2353  // by the compiler.
  2354  //
  2355  // StructOf currently does not generate wrapper methods for embedded
  2356  // fields and panics if passed unexported StructFields.
  2357  // These limitations may be lifted in a future version.
  2358  func StructOf(fields []StructField) Type {
  2359  	var (
  2360  		hash       = fnv1(0, []byte("struct {")...)
  2361  		size       uintptr
  2362  		typalign   uint8
  2363  		comparable = true
  2364  		methods    []method
  2365  
  2366  		fs   = make([]structField, len(fields))
  2367  		repr = make([]byte, 0, 64)
  2368  		fset = map[string]struct{}{} // fields' names
  2369  
  2370  		hasGCProg = false // records whether a struct-field type has a GCProg
  2371  	)
  2372  
  2373  	lastzero := uintptr(0)
  2374  	repr = append(repr, "struct {"...)
  2375  	pkgpath := ""
  2376  	for i, field := range fields {
  2377  		if field.Name == "" {
  2378  			panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
  2379  		}
  2380  		if !isValidFieldName(field.Name) {
  2381  			panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
  2382  		}
  2383  		if field.Type == nil {
  2384  			panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
  2385  		}
  2386  		f, fpkgpath := runtimeStructField(field)
  2387  		ft := f.typ
  2388  		if ft.kind&kindGCProg != 0 {
  2389  			hasGCProg = true
  2390  		}
  2391  		if fpkgpath != "" {
  2392  			if pkgpath == "" {
  2393  				pkgpath = fpkgpath
  2394  			} else if pkgpath != fpkgpath {
  2395  				panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
  2396  			}
  2397  		}
  2398  
  2399  		// Update string and hash
  2400  		name := f.name.name()
  2401  		hash = fnv1(hash, []byte(name)...)
  2402  		repr = append(repr, (" " + name)...)
  2403  		if f.embedded() {
  2404  			// Embedded field
  2405  			if f.typ.Kind() == Ptr {
  2406  				// Embedded ** and *interface{} are illegal
  2407  				elem := ft.Elem()
  2408  				if k := elem.Kind(); k == Ptr || k == Interface {
  2409  					panic("reflect.StructOf: illegal embedded field type " + ft.String())
  2410  				}
  2411  			}
  2412  
  2413  			switch f.typ.Kind() {
  2414  			case Interface:
  2415  				ift := (*interfaceType)(unsafe.Pointer(ft))
  2416  				for im, m := range ift.methods {
  2417  					if ift.nameOff(m.name).pkgPath() != "" {
  2418  						// TODO(sbinet).  Issue 15924.
  2419  						panic("reflect: embedded interface with unexported method(s) not implemented")
  2420  					}
  2421  
  2422  					var (
  2423  						mtyp    = ift.typeOff(m.typ)
  2424  						ifield  = i
  2425  						imethod = im
  2426  						ifn     Value
  2427  						tfn     Value
  2428  					)
  2429  
  2430  					if ft.kind&kindDirectIface != 0 {
  2431  						tfn = MakeFunc(mtyp, func(in []Value) []Value {
  2432  							var args []Value
  2433  							var recv = in[0]
  2434  							if len(in) > 1 {
  2435  								args = in[1:]
  2436  							}
  2437  							return recv.Field(ifield).Method(imethod).Call(args)
  2438  						})
  2439  						ifn = MakeFunc(mtyp, func(in []Value) []Value {
  2440  							var args []Value
  2441  							var recv = in[0]
  2442  							if len(in) > 1 {
  2443  								args = in[1:]
  2444  							}
  2445  							return recv.Field(ifield).Method(imethod).Call(args)
  2446  						})
  2447  					} else {
  2448  						tfn = MakeFunc(mtyp, func(in []Value) []Value {
  2449  							var args []Value
  2450  							var recv = in[0]
  2451  							if len(in) > 1 {
  2452  								args = in[1:]
  2453  							}
  2454  							return recv.Field(ifield).Method(imethod).Call(args)
  2455  						})
  2456  						ifn = MakeFunc(mtyp, func(in []Value) []Value {
  2457  							var args []Value
  2458  							var recv = Indirect(in[0])
  2459  							if len(in) > 1 {
  2460  								args = in[1:]
  2461  							}
  2462  							return recv.Field(ifield).Method(imethod).Call(args)
  2463  						})
  2464  					}
  2465  
  2466  					methods = append(methods, method{
  2467  						name: resolveReflectName(ift.nameOff(m.name)),
  2468  						mtyp: resolveReflectType(mtyp),
  2469  						ifn:  resolveReflectText(unsafe.Pointer(&ifn)),
  2470  						tfn:  resolveReflectText(unsafe.Pointer(&tfn)),
  2471  					})
  2472  				}
  2473  			case Ptr:
  2474  				ptr := (*ptrType)(unsafe.Pointer(ft))
  2475  				if unt := ptr.uncommon(); unt != nil {
  2476  					if i > 0 && unt.mcount > 0 {
  2477  						// Issue 15924.
  2478  						panic("reflect: embedded type with methods not implemented if type is not first field")
  2479  					}
  2480  					if len(fields) > 1 {
  2481  						panic("reflect: embedded type with methods not implemented if there is more than one field")
  2482  					}
  2483  					for _, m := range unt.methods() {
  2484  						mname := ptr.nameOff(m.name)
  2485  						if mname.pkgPath() != "" {
  2486  							// TODO(sbinet).
  2487  							// Issue 15924.
  2488  							panic("reflect: embedded interface with unexported method(s) not implemented")
  2489  						}
  2490  						methods = append(methods, method{
  2491  							name: resolveReflectName(mname),
  2492  							mtyp: resolveReflectType(ptr.typeOff(m.mtyp)),
  2493  							ifn:  resolveReflectText(ptr.textOff(m.ifn)),
  2494  							tfn:  resolveReflectText(ptr.textOff(m.tfn)),
  2495  						})
  2496  					}
  2497  				}
  2498  				if unt := ptr.elem.uncommon(); unt != nil {
  2499  					for _, m := range unt.methods() {
  2500  						mname := ptr.nameOff(m.name)
  2501  						if mname.pkgPath() != "" {
  2502  							// TODO(sbinet)
  2503  							// Issue 15924.
  2504  							panic("reflect: embedded interface with unexported method(s) not implemented")
  2505  						}
  2506  						methods = append(methods, method{
  2507  							name: resolveReflectName(mname),
  2508  							mtyp: resolveReflectType(ptr.elem.typeOff(m.mtyp)),
  2509  							ifn:  resolveReflectText(ptr.elem.textOff(m.ifn)),
  2510  							tfn:  resolveReflectText(ptr.elem.textOff(m.tfn)),
  2511  						})
  2512  					}
  2513  				}
  2514  			default:
  2515  				if unt := ft.uncommon(); unt != nil {
  2516  					if i > 0 && unt.mcount > 0 {
  2517  						// Issue 15924.
  2518  						panic("reflect: embedded type with methods not implemented if type is not first field")
  2519  					}
  2520  					if len(fields) > 1 && ft.kind&kindDirectIface != 0 {
  2521  						panic("reflect: embedded type with methods not implemented for non-pointer type")
  2522  					}
  2523  					for _, m := range unt.methods() {
  2524  						mname := ft.nameOff(m.name)
  2525  						if mname.pkgPath() != "" {
  2526  							// TODO(sbinet)
  2527  							// Issue 15924.
  2528  							panic("reflect: embedded interface with unexported method(s) not implemented")
  2529  						}
  2530  						methods = append(methods, method{
  2531  							name: resolveReflectName(mname),
  2532  							mtyp: resolveReflectType(ft.typeOff(m.mtyp)),
  2533  							ifn:  resolveReflectText(ft.textOff(m.ifn)),
  2534  							tfn:  resolveReflectText(ft.textOff(m.tfn)),
  2535  						})
  2536  
  2537  					}
  2538  				}
  2539  			}
  2540  		}
  2541  		if _, dup := fset[name]; dup {
  2542  			panic("reflect.StructOf: duplicate field " + name)
  2543  		}
  2544  		fset[name] = struct{}{}
  2545  
  2546  		hash = fnv1(hash, byte(ft.hash>>24), byte(ft.hash>>16), byte(ft.hash>>8), byte(ft.hash))
  2547  
  2548  		repr = append(repr, (" " + ft.String())...)
  2549  		if f.name.tagLen() > 0 {
  2550  			hash = fnv1(hash, []byte(f.name.tag())...)
  2551  			repr = append(repr, (" " + strconv.Quote(f.name.tag()))...)
  2552  		}
  2553  		if i < len(fields)-1 {
  2554  			repr = append(repr, ';')
  2555  		}
  2556  
  2557  		comparable = comparable && (ft.equal != nil)
  2558  
  2559  		offset := align(size, uintptr(ft.align))
  2560  		if ft.align > typalign {
  2561  			typalign = ft.align
  2562  		}
  2563  		size = offset + ft.size
  2564  		f.offsetEmbed |= offset << 1
  2565  
  2566  		if ft.size == 0 {
  2567  			lastzero = size
  2568  		}
  2569  
  2570  		fs[i] = f
  2571  	}
  2572  
  2573  	if size > 0 && lastzero == size {
  2574  		// This is a non-zero sized struct that ends in a
  2575  		// zero-sized field. We add an extra byte of padding,
  2576  		// to ensure that taking the address of the final
  2577  		// zero-sized field can't manufacture a pointer to the
  2578  		// next object in the heap. See issue 9401.
  2579  		size++
  2580  	}
  2581  
  2582  	var typ *structType
  2583  	var ut *uncommonType
  2584  
  2585  	if len(methods) == 0 {
  2586  		t := new(structTypeUncommon)
  2587  		typ = &t.structType
  2588  		ut = &t.u
  2589  	} else {
  2590  		// A *rtype representing a struct is followed directly in memory by an
  2591  		// array of method objects representing the methods attached to the
  2592  		// struct. To get the same layout for a run time generated type, we
  2593  		// need an array directly following the uncommonType memory.
  2594  		// A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN.
  2595  		tt := New(StructOf([]StructField{
  2596  			{Name: "S", Type: TypeOf(structType{})},
  2597  			{Name: "U", Type: TypeOf(uncommonType{})},
  2598  			{Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
  2599  		}))
  2600  
  2601  		typ = (*structType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
  2602  		ut = (*uncommonType)(unsafe.Pointer(tt.Elem().Field(1).UnsafeAddr()))
  2603  
  2604  		copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]method), methods)
  2605  	}
  2606  	// TODO(sbinet): Once we allow embedding multiple types,
  2607  	// methods will need to be sorted like the compiler does.
  2608  	// TODO(sbinet): Once we allow non-exported methods, we will
  2609  	// need to compute xcount as the number of exported methods.
  2610  	ut.mcount = uint16(len(methods))
  2611  	ut.xcount = ut.mcount
  2612  	ut.moff = uint32(unsafe.Sizeof(uncommonType{}))
  2613  
  2614  	if len(fs) > 0 {
  2615  		repr = append(repr, ' ')
  2616  	}
  2617  	repr = append(repr, '}')
  2618  	hash = fnv1(hash, '}')
  2619  	str := string(repr)
  2620  
  2621  	// Round the size up to be a multiple of the alignment.
  2622  	size = align(size, uintptr(typalign))
  2623  
  2624  	// Make the struct type.
  2625  	var istruct interface{} = struct{}{}
  2626  	prototype := *(**structType)(unsafe.Pointer(&istruct))
  2627  	*typ = *prototype
  2628  	typ.fields = fs
  2629  	if pkgpath != "" {
  2630  		typ.pkgPath = newName(pkgpath, "", false)
  2631  	}
  2632  
  2633  	// Look in cache.
  2634  	if ts, ok := structLookupCache.m.Load(hash); ok {
  2635  		for _, st := range ts.([]Type) {
  2636  			t := st.common()
  2637  			if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
  2638  				return t
  2639  			}
  2640  		}
  2641  	}
  2642  
  2643  	// Not in cache, lock and retry.
  2644  	structLookupCache.Lock()
  2645  	defer structLookupCache.Unlock()
  2646  	if ts, ok := structLookupCache.m.Load(hash); ok {
  2647  		for _, st := range ts.([]Type) {
  2648  			t := st.common()
  2649  			if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
  2650  				return t
  2651  			}
  2652  		}
  2653  	}
  2654  
  2655  	addToCache := func(t Type) Type {
  2656  		var ts []Type
  2657  		if ti, ok := structLookupCache.m.Load(hash); ok {
  2658  			ts = ti.([]Type)
  2659  		}
  2660  		structLookupCache.m.Store(hash, append(ts, t))
  2661  		return t
  2662  	}
  2663  
  2664  	// Look in known types.
  2665  	for _, t := range typesByString(str) {
  2666  		if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
  2667  			// even if 't' wasn't a structType with methods, we should be ok
  2668  			// as the 'u uncommonType' field won't be accessed except when
  2669  			// tflag&tflagUncommon is set.
  2670  			return addToCache(t)
  2671  		}
  2672  	}
  2673  
  2674  	typ.str = resolveReflectName(newName(str, "", false))
  2675  	typ.tflag = 0 // TODO: set tflagRegularMemory
  2676  	typ.hash = hash
  2677  	typ.size = size
  2678  	typ.ptrdata = typeptrdata(typ.common())
  2679  	typ.align = typalign
  2680  	typ.fieldAlign = typalign
  2681  	typ.ptrToThis = 0
  2682  	if len(methods) > 0 {
  2683  		typ.tflag |= tflagUncommon
  2684  	}
  2685  
  2686  	if hasGCProg {
  2687  		lastPtrField := 0
  2688  		for i, ft := range fs {
  2689  			if ft.typ.pointers() {
  2690  				lastPtrField = i
  2691  			}
  2692  		}
  2693  		prog := []byte{0, 0, 0, 0} // will be length of prog
  2694  		var off uintptr
  2695  		for i, ft := range fs {
  2696  			if i > lastPtrField {
  2697  				// gcprog should not include anything for any field after
  2698  				// the last field that contains pointer data
  2699  				break
  2700  			}
  2701  			if !ft.typ.pointers() {
  2702  				// Ignore pointerless fields.
  2703  				continue
  2704  			}
  2705  			// Pad to start of this field with zeros.
  2706  			if ft.offset() > off {
  2707  				n := (ft.offset() - off) / ptrSize
  2708  				prog = append(prog, 0x01, 0x00) // emit a 0 bit
  2709  				if n > 1 {
  2710  					prog = append(prog, 0x81)      // repeat previous bit
  2711  					prog = appendVarint(prog, n-1) // n-1 times
  2712  				}
  2713  				off = ft.offset()
  2714  			}
  2715  
  2716  			prog = appendGCProg(prog, ft.typ)
  2717  			off += ft.typ.ptrdata
  2718  		}
  2719  		prog = append(prog, 0)
  2720  		*(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
  2721  		typ.kind |= kindGCProg
  2722  		typ.gcdata = &prog[0]
  2723  	} else {
  2724  		typ.kind &^= kindGCProg
  2725  		bv := new(bitVector)
  2726  		addTypeBits(bv, 0, typ.common())
  2727  		if len(bv.data) > 0 {
  2728  			typ.gcdata = &bv.data[0]
  2729  		}
  2730  	}
  2731  	typ.equal = nil
  2732  	if comparable {
  2733  		typ.equal = func(p, q unsafe.Pointer) bool {
  2734  			for _, ft := range typ.fields {
  2735  				pi := add(p, ft.offset(), "&x.field safe")
  2736  				qi := add(q, ft.offset(), "&x.field safe")
  2737  				if !ft.typ.equal(pi, qi) {
  2738  					return false
  2739  				}
  2740  			}
  2741  			return true
  2742  		}
  2743  	}
  2744  
  2745  	switch {
  2746  	case len(fs) == 1 && !ifaceIndir(fs[0].typ):
  2747  		// structs of 1 direct iface type can be direct
  2748  		typ.kind |= kindDirectIface
  2749  	default:
  2750  		typ.kind &^= kindDirectIface
  2751  	}
  2752  
  2753  	return addToCache(&typ.rtype)
  2754  }
  2755  
  2756  // runtimeStructField takes a StructField value passed to StructOf and
  2757  // returns both the corresponding internal representation, of type
  2758  // structField, and the pkgpath value to use for this field.
  2759  func runtimeStructField(field StructField) (structField, string) {
  2760  	if field.Anonymous && field.PkgPath != "" {
  2761  		panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
  2762  	}
  2763  
  2764  	exported := field.PkgPath == ""
  2765  	if exported {
  2766  		// Best-effort check for misuse.
  2767  		// Since this field will be treated as exported, not much harm done if Unicode lowercase slips through.
  2768  		c := field.Name[0]
  2769  		if 'a' <= c && c <= 'z' || c == '_' {
  2770  			panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
  2771  		}
  2772  	}
  2773  
  2774  	offsetEmbed := uintptr(0)
  2775  	if field.Anonymous {
  2776  		offsetEmbed |= 1
  2777  	}
  2778  
  2779  	resolveReflectType(field.Type.common()) // install in runtime
  2780  	f := structField{
  2781  		name:        newName(field.Name, string(field.Tag), exported),
  2782  		typ:         field.Type.common(),
  2783  		offsetEmbed: offsetEmbed,
  2784  	}
  2785  	return f, field.PkgPath
  2786  }
  2787  
  2788  // typeptrdata returns the length in bytes of the prefix of t
  2789  // containing pointer data. Anything after this offset is scalar data.
  2790  // keep in sync with ../cmd/compile/internal/gc/reflect.go
  2791  func typeptrdata(t *rtype) uintptr {
  2792  	switch t.Kind() {
  2793  	case Struct:
  2794  		st := (*structType)(unsafe.Pointer(t))
  2795  		// find the last field that has pointers.
  2796  		field := -1
  2797  		for i := range st.fields {
  2798  			ft := st.fields[i].typ
  2799  			if ft.pointers() {
  2800  				field = i
  2801  			}
  2802  		}
  2803  		if field == -1 {
  2804  			return 0
  2805  		}
  2806  		f := st.fields[field]
  2807  		return f.offset() + f.typ.ptrdata
  2808  
  2809  	default:
  2810  		panic("reflect.typeptrdata: unexpected type, " + t.String())
  2811  	}
  2812  }
  2813  
  2814  // See cmd/compile/internal/gc/reflect.go for derivation of constant.
  2815  const maxPtrmaskBytes = 2048
  2816  
  2817  // ArrayOf returns the array type with the given count and element type.
  2818  // For example, if t represents int, ArrayOf(5, t) represents [5]int.
  2819  //
  2820  // If the resulting type would be larger than the available address space,
  2821  // ArrayOf panics.
  2822  func ArrayOf(count int, elem Type) Type {
  2823  	typ := elem.(*rtype)
  2824  
  2825  	// Look in cache.
  2826  	ckey := cacheKey{Array, typ, nil, uintptr(count)}
  2827  	if array, ok := lookupCache.Load(ckey); ok {
  2828  		return array.(Type)
  2829  	}
  2830  
  2831  	// Look in known types.
  2832  	s := "[" + strconv.Itoa(count) + "]" + typ.String()
  2833  	for _, tt := range typesByString(s) {
  2834  		array := (*arrayType)(unsafe.Pointer(tt))
  2835  		if array.elem == typ {
  2836  			ti, _ := lookupCache.LoadOrStore(ckey, tt)
  2837  			return ti.(Type)
  2838  		}
  2839  	}
  2840  
  2841  	// Make an array type.
  2842  	var iarray interface{} = [1]unsafe.Pointer{}
  2843  	prototype := *(**arrayType)(unsafe.Pointer(&iarray))
  2844  	array := *prototype
  2845  	array.tflag = typ.tflag & tflagRegularMemory
  2846  	array.str = resolveReflectName(newName(s, "", false))
  2847  	array.hash = fnv1(typ.hash, '[')
  2848  	for n := uint32(count); n > 0; n >>= 8 {
  2849  		array.hash = fnv1(array.hash, byte(n))
  2850  	}
  2851  	array.hash = fnv1(array.hash, ']')
  2852  	array.elem = typ
  2853  	array.ptrToThis = 0
  2854  	if typ.size > 0 {
  2855  		max := ^uintptr(0) / typ.size
  2856  		if uintptr(count) > max {
  2857  			panic("reflect.ArrayOf: array size would exceed virtual address space")
  2858  		}
  2859  	}
  2860  	array.size = typ.size * uintptr(count)
  2861  	if count > 0 && typ.ptrdata != 0 {
  2862  		array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata
  2863  	}
  2864  	array.align = typ.align
  2865  	array.fieldAlign = typ.fieldAlign
  2866  	array.len = uintptr(count)
  2867  	array.slice = SliceOf(elem).(*rtype)
  2868  
  2869  	switch {
  2870  	case typ.ptrdata == 0 || array.size == 0:
  2871  		// No pointers.
  2872  		array.gcdata = nil
  2873  		array.ptrdata = 0
  2874  
  2875  	case count == 1:
  2876  		// In memory, 1-element array looks just like the element.
  2877  		array.kind |= typ.kind & kindGCProg
  2878  		array.gcdata = typ.gcdata
  2879  		array.ptrdata = typ.ptrdata
  2880  
  2881  	case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*ptrSize:
  2882  		// Element is small with pointer mask; array is still small.
  2883  		// Create direct pointer mask by turning each 1 bit in elem
  2884  		// into count 1 bits in larger mask.
  2885  		mask := make([]byte, (array.ptrdata/ptrSize+7)/8)
  2886  		emitGCMask(mask, 0, typ, array.len)
  2887  		array.gcdata = &mask[0]
  2888  
  2889  	default:
  2890  		// Create program that emits one element
  2891  		// and then repeats to make the array.
  2892  		prog := []byte{0, 0, 0, 0} // will be length of prog
  2893  		prog = appendGCProg(prog, typ)
  2894  		// Pad from ptrdata to size.
  2895  		elemPtrs := typ.ptrdata / ptrSize
  2896  		elemWords := typ.size / ptrSize
  2897  		if elemPtrs < elemWords {
  2898  			// Emit literal 0 bit, then repeat as needed.
  2899  			prog = append(prog, 0x01, 0x00)
  2900  			if elemPtrs+1 < elemWords {
  2901  				prog = append(prog, 0x81)
  2902  				prog = appendVarint(prog, elemWords-elemPtrs-1)
  2903  			}
  2904  		}
  2905  		// Repeat count-1 times.
  2906  		if elemWords < 0x80 {
  2907  			prog = append(prog, byte(elemWords|0x80))
  2908  		} else {
  2909  			prog = append(prog, 0x80)
  2910  			prog = appendVarint(prog, elemWords)
  2911  		}
  2912  		prog = appendVarint(prog, uintptr(count)-1)
  2913  		prog = append(prog, 0)
  2914  		*(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
  2915  		array.kind |= kindGCProg
  2916  		array.gcdata = &prog[0]
  2917  		array.ptrdata = array.size // overestimate but ok; must match program
  2918  	}
  2919  
  2920  	etyp := typ.common()
  2921  	esize := etyp.Size()
  2922  
  2923  	array.equal = nil
  2924  	if eequal := etyp.equal; eequal != nil {
  2925  		array.equal = func(p, q unsafe.Pointer) bool {
  2926  			for i := 0; i < count; i++ {
  2927  				pi := arrayAt(p, i, esize, "i < count")
  2928  				qi := arrayAt(q, i, esize, "i < count")
  2929  				if !eequal(pi, qi) {
  2930  					return false
  2931  				}
  2932  
  2933  			}
  2934  			return true
  2935  		}
  2936  	}
  2937  
  2938  	switch {
  2939  	case count == 1 && !ifaceIndir(typ):
  2940  		// array of 1 direct iface type can be direct
  2941  		array.kind |= kindDirectIface
  2942  	default:
  2943  		array.kind &^= kindDirectIface
  2944  	}
  2945  
  2946  	ti, _ := lookupCache.LoadOrStore(ckey, &array.rtype)
  2947  	return ti.(Type)
  2948  }
  2949  
  2950  func appendVarint(x []byte, v uintptr) []byte {
  2951  	for ; v >= 0x80; v >>= 7 {
  2952  		x = append(x, byte(v|0x80))
  2953  	}
  2954  	x = append(x, byte(v))
  2955  	return x
  2956  }
  2957  
  2958  // toType converts from a *rtype to a Type that can be returned
  2959  // to the client of package reflect. In gc, the only concern is that
  2960  // a nil *rtype must be replaced by a nil Type, but in gccgo this
  2961  // function takes care of ensuring that multiple *rtype for the same
  2962  // type are coalesced into a single Type.
  2963  func toType(t *rtype) Type {
  2964  	if t == nil {
  2965  		return nil
  2966  	}
  2967  	return t
  2968  }
  2969  
  2970  type layoutKey struct {
  2971  	ftyp *funcType // function signature
  2972  	rcvr *rtype    // receiver type, or nil if none
  2973  }
  2974  
  2975  type layoutType struct {
  2976  	t         *rtype
  2977  	argSize   uintptr // size of arguments
  2978  	retOffset uintptr // offset of return values.
  2979  	stack     *bitVector
  2980  	framePool *sync.Pool
  2981  }
  2982  
  2983  var layoutCache sync.Map // map[layoutKey]layoutType
  2984  
  2985  // funcLayout computes a struct type representing the layout of the
  2986  // function arguments and return values for the function type t.
  2987  // If rcvr != nil, rcvr specifies the type of the receiver.
  2988  // The returned type exists only for GC, so we only fill out GC relevant info.
  2989  // Currently, that's just size and the GC program. We also fill in
  2990  // the name for possible debugging use.
  2991  func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stk *bitVector, framePool *sync.Pool) {
  2992  	if t.Kind() != Func {
  2993  		panic("reflect: funcLayout of non-func type " + t.String())
  2994  	}
  2995  	if rcvr != nil && rcvr.Kind() == Interface {
  2996  		panic("reflect: funcLayout with interface receiver " + rcvr.String())
  2997  	}
  2998  	k := layoutKey{t, rcvr}
  2999  	if lti, ok := layoutCache.Load(k); ok {
  3000  		lt := lti.(layoutType)
  3001  		return lt.t, lt.argSize, lt.retOffset, lt.stack, lt.framePool
  3002  	}
  3003  
  3004  	// compute gc program & stack bitmap for arguments
  3005  	ptrmap := new(bitVector)
  3006  	var offset uintptr
  3007  	if rcvr != nil {
  3008  		// Reflect uses the "interface" calling convention for
  3009  		// methods, where receivers take one word of argument
  3010  		// space no matter how big they actually are.
  3011  		if ifaceIndir(rcvr) || rcvr.pointers() {
  3012  			ptrmap.append(1)
  3013  		} else {
  3014  			ptrmap.append(0)
  3015  		}
  3016  		offset += ptrSize
  3017  	}
  3018  	for _, arg := range t.in() {
  3019  		offset += -offset & uintptr(arg.align-1)
  3020  		addTypeBits(ptrmap, offset, arg)
  3021  		offset += arg.size
  3022  	}
  3023  	argSize = offset
  3024  	offset += -offset & (ptrSize - 1)
  3025  	retOffset = offset
  3026  	for _, res := range t.out() {
  3027  		offset += -offset & uintptr(res.align-1)
  3028  		addTypeBits(ptrmap, offset, res)
  3029  		offset += res.size
  3030  	}
  3031  	offset += -offset & (ptrSize - 1)
  3032  
  3033  	// build dummy rtype holding gc program
  3034  	x := &rtype{
  3035  		align:   ptrSize,
  3036  		size:    offset,
  3037  		ptrdata: uintptr(ptrmap.n) * ptrSize,
  3038  	}
  3039  	if ptrmap.n > 0 {
  3040  		x.gcdata = &ptrmap.data[0]
  3041  	}
  3042  
  3043  	var s string
  3044  	if rcvr != nil {
  3045  		s = "methodargs(" + rcvr.String() + ")(" + t.String() + ")"
  3046  	} else {
  3047  		s = "funcargs(" + t.String() + ")"
  3048  	}
  3049  	x.str = resolveReflectName(newName(s, "", false))
  3050  
  3051  	// cache result for future callers
  3052  	framePool = &sync.Pool{New: func() interface{} {
  3053  		return unsafe_New(x)
  3054  	}}
  3055  	lti, _ := layoutCache.LoadOrStore(k, layoutType{
  3056  		t:         x,
  3057  		argSize:   argSize,
  3058  		retOffset: retOffset,
  3059  		stack:     ptrmap,
  3060  		framePool: framePool,
  3061  	})
  3062  	lt := lti.(layoutType)
  3063  	return lt.t, lt.argSize, lt.retOffset, lt.stack, lt.framePool
  3064  }
  3065  
  3066  // ifaceIndir reports whether t is stored indirectly in an interface value.
  3067  func ifaceIndir(t *rtype) bool {
  3068  	return t.kind&kindDirectIface == 0
  3069  }
  3070  
  3071  // Note: this type must agree with runtime.bitvector.
  3072  type bitVector struct {
  3073  	n    uint32 // number of bits
  3074  	data []byte
  3075  }
  3076  
  3077  // append a bit to the bitmap.
  3078  func (bv *bitVector) append(bit uint8) {
  3079  	if bv.n%8 == 0 {
  3080  		bv.data = append(bv.data, 0)
  3081  	}
  3082  	bv.data[bv.n/8] |= bit << (bv.n % 8)
  3083  	bv.n++
  3084  }
  3085  
  3086  func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
  3087  	if t.ptrdata == 0 {
  3088  		return
  3089  	}
  3090  
  3091  	switch Kind(t.kind & kindMask) {
  3092  	case Chan, Func, Map, Ptr, Slice, String, UnsafePointer:
  3093  		// 1 pointer at start of representation
  3094  		for bv.n < uint32(offset/uintptr(ptrSize)) {
  3095  			bv.append(0)
  3096  		}
  3097  		bv.append(1)
  3098  
  3099  	case Interface:
  3100  		// 2 pointers
  3101  		for bv.n < uint32(offset/uintptr(ptrSize)) {
  3102  			bv.append(0)
  3103  		}
  3104  		bv.append(1)
  3105  		bv.append(1)
  3106  
  3107  	case Array:
  3108  		// repeat inner type
  3109  		tt := (*arrayType)(unsafe.Pointer(t))
  3110  		for i := 0; i < int(tt.len); i++ {
  3111  			addTypeBits(bv, offset+uintptr(i)*tt.elem.size, tt.elem)
  3112  		}
  3113  
  3114  	case Struct:
  3115  		// apply fields
  3116  		tt := (*structType)(unsafe.Pointer(t))
  3117  		for i := range tt.fields {
  3118  			f := &tt.fields[i]
  3119  			addTypeBits(bv, offset+f.offset(), f.typ)
  3120  		}
  3121  	}
  3122  }
  3123  

View as plain text