Source file src/internal/reflectlite/type.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package reflectlite implements lightweight version of reflect, not using
     6  // any package except for "runtime", "unsafe", and "internal/abi"
     7  package reflectlite
     8  
     9  import (
    10  	"internal/abi"
    11  	"unsafe"
    12  )
    13  
    14  // Type is the representation of a Go type.
    15  //
    16  // Not all methods apply to all kinds of types. Restrictions,
    17  // if any, are noted in the documentation for each method.
    18  // Use the Kind method to find out the kind of type before
    19  // calling kind-specific methods. Calling a method
    20  // inappropriate to the kind of type causes a run-time panic.
    21  //
    22  // Type values are comparable, such as with the == operator,
    23  // so they can be used as map keys.
    24  // Two Type values are equal if they represent identical types.
    25  type Type interface {
    26  	// Methods applicable to all types.
    27  
    28  	// Name returns the type's name within its package for a defined type.
    29  	// For other (non-defined) types it returns the empty string.
    30  	Name() string
    31  
    32  	// PkgPath returns a defined type's package path, that is, the import path
    33  	// that uniquely identifies the package, such as "encoding/base64".
    34  	// If the type was predeclared (string, error) or not defined (*T, struct{},
    35  	// []int, or A where A is an alias for a non-defined type), the package path
    36  	// will be the empty string.
    37  	PkgPath() string
    38  
    39  	// Size returns the number of bytes needed to store
    40  	// a value of the given type; it is analogous to unsafe.Sizeof.
    41  	Size() uintptr
    42  
    43  	// Kind returns the specific kind of this type.
    44  	Kind() Kind
    45  
    46  	// Implements reports whether the type implements the interface type u.
    47  	Implements(u Type) bool
    48  
    49  	// AssignableTo reports whether a value of the type is assignable to type u.
    50  	AssignableTo(u Type) bool
    51  
    52  	// Comparable reports whether values of this type are comparable.
    53  	Comparable() bool
    54  
    55  	// String returns a string representation of the type.
    56  	// The string representation may use shortened package names
    57  	// (e.g., base64 instead of "encoding/base64") and is not
    58  	// guaranteed to be unique among types. To test for type identity,
    59  	// compare the Types directly.
    60  	String() string
    61  
    62  	// Elem returns a type's element type.
    63  	// It panics if the type's Kind is not Ptr.
    64  	Elem() Type
    65  
    66  	common() *abi.Type
    67  	uncommon() *uncommonType
    68  }
    69  
    70  /*
    71   * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
    72   * A few are known to ../runtime/type.go to convey to debuggers.
    73   * They are also known to ../runtime/type.go.
    74   */
    75  
    76  // A Kind represents the specific kind of type that a Type represents.
    77  // The zero Kind is not a valid kind.
    78  type Kind = abi.Kind
    79  
    80  const Ptr = abi.Pointer
    81  
    82  const (
    83  	// Import-and-export these constants as necessary
    84  	Interface = abi.Interface
    85  	Slice     = abi.Slice
    86  	String    = abi.String
    87  	Struct    = abi.Struct
    88  )
    89  
    90  type nameOff = abi.NameOff
    91  type typeOff = abi.TypeOff
    92  type textOff = abi.TextOff
    93  
    94  type rtype struct {
    95  	*abi.Type
    96  }
    97  
    98  // uncommonType is present only for defined types or types with methods
    99  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   100  // Using a pointer to this struct reduces the overall size required
   101  // to describe a non-defined type with no methods.
   102  type uncommonType = abi.UncommonType
   103  
   104  // arrayType represents a fixed array type.
   105  type arrayType = abi.ArrayType
   106  
   107  // chanType represents a channel type.
   108  type chanType = abi.ChanType
   109  
   110  type funcType = abi.FuncType
   111  
   112  type interfaceType = abi.InterfaceType
   113  
   114  // mapType represents a map type.
   115  type mapType struct {
   116  	rtype
   117  	Key    *abi.Type // map key type
   118  	Elem   *abi.Type // map element (value) type
   119  	Bucket *abi.Type // internal bucket structure
   120  	// function for hashing keys (ptr to key, seed) -> hash
   121  	Hasher     func(unsafe.Pointer, uintptr) uintptr
   122  	KeySize    uint8  // size of key slot
   123  	ValueSize  uint8  // size of value slot
   124  	BucketSize uint16 // size of bucket
   125  	Flags      uint32
   126  }
   127  
   128  // ptrType represents a pointer type.
   129  type ptrType = abi.PtrType
   130  
   131  // sliceType represents a slice type.
   132  type sliceType = abi.SliceType
   133  
   134  // structType represents a struct type.
   135  type structType = abi.StructType
   136  
   137  // name is an encoded type name with optional extra data.
   138  //
   139  // The first byte is a bit field containing:
   140  //
   141  //	1<<0 the name is exported
   142  //	1<<1 tag data follows the name
   143  //	1<<2 pkgPath nameOff follows the name and tag
   144  //
   145  // The next two bytes are the data length:
   146  //
   147  //	l := uint16(data[1])<<8 | uint16(data[2])
   148  //
   149  // Bytes [3:3+l] are the string data.
   150  //
   151  // If tag data follows then bytes 3+l and 3+l+1 are the tag length,
   152  // with the data following.
   153  //
   154  // If the import path follows, then 4 bytes at the end of
   155  // the data form a nameOff. The import path is only set for concrete
   156  // methods that are defined in a different package than their type.
   157  //
   158  // If a name starts with "*", then the exported bit represents
   159  // whether the pointed to type is exported.
   160  type name struct {
   161  	bytes *byte
   162  }
   163  
   164  func (n name) data(off int, whySafe string) *byte {
   165  	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
   166  }
   167  
   168  func (n name) isExported() bool {
   169  	return (*n.bytes)&(1<<0) != 0
   170  }
   171  
   172  func (n name) hasTag() bool {
   173  	return (*n.bytes)&(1<<1) != 0
   174  }
   175  
   176  func (n name) embedded() bool {
   177  	return (*n.bytes)&(1<<3) != 0
   178  }
   179  
   180  // readVarint parses a varint as encoded by encoding/binary.
   181  // It returns the number of encoded bytes and the encoded value.
   182  func (n name) readVarint(off int) (int, int) {
   183  	v := 0
   184  	for i := 0; ; i++ {
   185  		x := *n.data(off+i, "read varint")
   186  		v += int(x&0x7f) << (7 * i)
   187  		if x&0x80 == 0 {
   188  			return i + 1, v
   189  		}
   190  	}
   191  }
   192  
   193  func (n name) name() string {
   194  	if n.bytes == nil {
   195  		return ""
   196  	}
   197  	i, l := n.readVarint(1)
   198  	return unsafe.String(n.data(1+i, "non-empty string"), l)
   199  }
   200  
   201  func (n name) tag() string {
   202  	if !n.hasTag() {
   203  		return ""
   204  	}
   205  	i, l := n.readVarint(1)
   206  	i2, l2 := n.readVarint(1 + i + l)
   207  	return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
   208  }
   209  
   210  func pkgPath(n abi.Name) string {
   211  	if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
   212  		return ""
   213  	}
   214  	i, l := n.ReadVarint(1)
   215  	off := 1 + i + l
   216  	if n.HasTag() {
   217  		i2, l2 := n.ReadVarint(off)
   218  		off += i2 + l2
   219  	}
   220  	var nameOff int32
   221  	// Note that this field may not be aligned in memory,
   222  	// so we cannot use a direct int32 assignment here.
   223  	copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
   224  	pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
   225  	return pkgPathName.name()
   226  }
   227  
   228  /*
   229   * The compiler knows the exact layout of all the data structures above.
   230   * The compiler does not know about the data structures and methods below.
   231   */
   232  
   233  // resolveNameOff resolves a name offset from a base pointer.
   234  // The (*rtype).nameOff method is a convenience wrapper for this function.
   235  // Implemented in the runtime package.
   236  //
   237  //go:noescape
   238  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
   239  
   240  // resolveTypeOff resolves an *rtype offset from a base type.
   241  // The (*rtype).typeOff method is a convenience wrapper for this function.
   242  // Implemented in the runtime package.
   243  //
   244  //go:noescape
   245  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   246  
   247  func (t rtype) nameOff(off nameOff) abi.Name {
   248  	return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
   249  }
   250  
   251  func (t rtype) typeOff(off typeOff) *abi.Type {
   252  	return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
   253  }
   254  
   255  func (t rtype) uncommon() *uncommonType {
   256  	return t.Uncommon()
   257  }
   258  
   259  func (t rtype) String() string {
   260  	s := t.nameOff(t.Str).Name()
   261  	if t.TFlag&abi.TFlagExtraStar != 0 {
   262  		return s[1:]
   263  	}
   264  	return s
   265  }
   266  
   267  func (t rtype) common() *abi.Type { return t.Type }
   268  
   269  func (t rtype) exportedMethods() []abi.Method {
   270  	ut := t.uncommon()
   271  	if ut == nil {
   272  		return nil
   273  	}
   274  	return ut.ExportedMethods()
   275  }
   276  
   277  func (t rtype) NumMethod() int {
   278  	tt := t.Type.InterfaceType()
   279  	if tt != nil {
   280  		return tt.NumMethod()
   281  	}
   282  	return len(t.exportedMethods())
   283  }
   284  
   285  func (t rtype) PkgPath() string {
   286  	if t.TFlag&abi.TFlagNamed == 0 {
   287  		return ""
   288  	}
   289  	ut := t.uncommon()
   290  	if ut == nil {
   291  		return ""
   292  	}
   293  	return t.nameOff(ut.PkgPath).Name()
   294  }
   295  
   296  func (t rtype) Name() string {
   297  	if !t.HasName() {
   298  		return ""
   299  	}
   300  	s := t.String()
   301  	i := len(s) - 1
   302  	sqBrackets := 0
   303  	for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
   304  		switch s[i] {
   305  		case ']':
   306  			sqBrackets++
   307  		case '[':
   308  			sqBrackets--
   309  		}
   310  		i--
   311  	}
   312  	return s[i+1:]
   313  }
   314  
   315  func toRType(t *abi.Type) rtype {
   316  	return rtype{t}
   317  }
   318  
   319  func elem(t *abi.Type) *abi.Type {
   320  	et := t.Elem()
   321  	if et != nil {
   322  		return et
   323  	}
   324  	panic("reflect: Elem of invalid type " + toRType(t).String())
   325  }
   326  
   327  func (t rtype) Elem() Type {
   328  	return toType(elem(t.common()))
   329  }
   330  
   331  func (t rtype) In(i int) Type {
   332  	tt := t.Type.FuncType()
   333  	if tt == nil {
   334  		panic("reflect: In of non-func type")
   335  	}
   336  	return toType(tt.InSlice()[i])
   337  }
   338  
   339  func (t rtype) Key() Type {
   340  	tt := t.Type.MapType()
   341  	if tt == nil {
   342  		panic("reflect: Key of non-map type")
   343  	}
   344  	return toType(tt.Key)
   345  }
   346  
   347  func (t rtype) Len() int {
   348  	tt := t.Type.ArrayType()
   349  	if tt == nil {
   350  		panic("reflect: Len of non-array type")
   351  	}
   352  	return int(tt.Len)
   353  }
   354  
   355  func (t rtype) NumField() int {
   356  	tt := t.Type.StructType()
   357  	if tt == nil {
   358  		panic("reflect: NumField of non-struct type")
   359  	}
   360  	return len(tt.Fields)
   361  }
   362  
   363  func (t rtype) NumIn() int {
   364  	tt := t.Type.FuncType()
   365  	if tt == nil {
   366  		panic("reflect: NumIn of non-func type")
   367  	}
   368  	return int(tt.InCount)
   369  }
   370  
   371  func (t rtype) NumOut() int {
   372  	tt := t.Type.FuncType()
   373  	if tt == nil {
   374  		panic("reflect: NumOut of non-func type")
   375  	}
   376  	return tt.NumOut()
   377  }
   378  
   379  func (t rtype) Out(i int) Type {
   380  	tt := t.Type.FuncType()
   381  	if tt == nil {
   382  		panic("reflect: Out of non-func type")
   383  	}
   384  	return toType(tt.OutSlice()[i])
   385  }
   386  
   387  // add returns p+x.
   388  //
   389  // The whySafe string is ignored, so that the function still inlines
   390  // as efficiently as p+x, but all call sites should use the string to
   391  // record why the addition is safe, which is to say why the addition
   392  // does not cause x to advance to the very end of p's allocation
   393  // and therefore point incorrectly at the next block in memory.
   394  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   395  	return unsafe.Pointer(uintptr(p) + x)
   396  }
   397  
   398  // TypeOf returns the reflection Type that represents the dynamic type of i.
   399  // If i is a nil interface value, TypeOf returns nil.
   400  func TypeOf(i any) Type {
   401  	eface := *(*emptyInterface)(unsafe.Pointer(&i))
   402  	// Noescape so this doesn't make i to escape. See the comment
   403  	// at Value.typ for why this is safe.
   404  	return toType((*abi.Type)(noescape(unsafe.Pointer(eface.typ))))
   405  }
   406  
   407  func (t rtype) Implements(u Type) bool {
   408  	if u == nil {
   409  		panic("reflect: nil type passed to Type.Implements")
   410  	}
   411  	if u.Kind() != Interface {
   412  		panic("reflect: non-interface type passed to Type.Implements")
   413  	}
   414  	return implements(u.common(), t.common())
   415  }
   416  
   417  func (t rtype) AssignableTo(u Type) bool {
   418  	if u == nil {
   419  		panic("reflect: nil type passed to Type.AssignableTo")
   420  	}
   421  	uu := u.common()
   422  	tt := t.common()
   423  	return directlyAssignable(uu, tt) || implements(uu, tt)
   424  }
   425  
   426  func (t rtype) Comparable() bool {
   427  	return t.Equal != nil
   428  }
   429  
   430  // implements reports whether the type V implements the interface type T.
   431  func implements(T, V *abi.Type) bool {
   432  	t := T.InterfaceType()
   433  	if t == nil {
   434  		return false
   435  	}
   436  	if len(t.Methods) == 0 {
   437  		return true
   438  	}
   439  	rT := toRType(T)
   440  	rV := toRType(V)
   441  
   442  	// The same algorithm applies in both cases, but the
   443  	// method tables for an interface type and a concrete type
   444  	// are different, so the code is duplicated.
   445  	// In both cases the algorithm is a linear scan over the two
   446  	// lists - T's methods and V's methods - simultaneously.
   447  	// Since method tables are stored in a unique sorted order
   448  	// (alphabetical, with no duplicate method names), the scan
   449  	// through V's methods must hit a match for each of T's
   450  	// methods along the way, or else V does not implement T.
   451  	// This lets us run the scan in overall linear time instead of
   452  	// the quadratic time  a naive search would require.
   453  	// See also ../runtime/iface.go.
   454  	if V.Kind() == Interface {
   455  		v := (*interfaceType)(unsafe.Pointer(V))
   456  		i := 0
   457  		for j := 0; j < len(v.Methods); j++ {
   458  			tm := &t.Methods[i]
   459  			tmName := rT.nameOff(tm.Name)
   460  			vm := &v.Methods[j]
   461  			vmName := rV.nameOff(vm.Name)
   462  			if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
   463  				if !tmName.IsExported() {
   464  					tmPkgPath := pkgPath(tmName)
   465  					if tmPkgPath == "" {
   466  						tmPkgPath = t.PkgPath.Name()
   467  					}
   468  					vmPkgPath := pkgPath(vmName)
   469  					if vmPkgPath == "" {
   470  						vmPkgPath = v.PkgPath.Name()
   471  					}
   472  					if tmPkgPath != vmPkgPath {
   473  						continue
   474  					}
   475  				}
   476  				if i++; i >= len(t.Methods) {
   477  					return true
   478  				}
   479  			}
   480  		}
   481  		return false
   482  	}
   483  
   484  	v := V.Uncommon()
   485  	if v == nil {
   486  		return false
   487  	}
   488  	i := 0
   489  	vmethods := v.Methods()
   490  	for j := 0; j < int(v.Mcount); j++ {
   491  		tm := &t.Methods[i]
   492  		tmName := rT.nameOff(tm.Name)
   493  		vm := vmethods[j]
   494  		vmName := rV.nameOff(vm.Name)
   495  		if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
   496  			if !tmName.IsExported() {
   497  				tmPkgPath := pkgPath(tmName)
   498  				if tmPkgPath == "" {
   499  					tmPkgPath = t.PkgPath.Name()
   500  				}
   501  				vmPkgPath := pkgPath(vmName)
   502  				if vmPkgPath == "" {
   503  					vmPkgPath = rV.nameOff(v.PkgPath).Name()
   504  				}
   505  				if tmPkgPath != vmPkgPath {
   506  					continue
   507  				}
   508  			}
   509  			if i++; i >= len(t.Methods) {
   510  				return true
   511  			}
   512  		}
   513  	}
   514  	return false
   515  }
   516  
   517  // directlyAssignable reports whether a value x of type V can be directly
   518  // assigned (using memmove) to a value of type T.
   519  // https://golang.org/doc/go_spec.html#Assignability
   520  // Ignoring the interface rules (implemented elsewhere)
   521  // and the ideal constant rules (no ideal constants at run time).
   522  func directlyAssignable(T, V *abi.Type) bool {
   523  	// x's type V is identical to T?
   524  	if T == V {
   525  		return true
   526  	}
   527  
   528  	// Otherwise at least one of T and V must not be defined
   529  	// and they must have the same kind.
   530  	if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
   531  		return false
   532  	}
   533  
   534  	// x's type T and V must  have identical underlying types.
   535  	return haveIdenticalUnderlyingType(T, V, true)
   536  }
   537  
   538  func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
   539  	if cmpTags {
   540  		return T == V
   541  	}
   542  
   543  	if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
   544  		return false
   545  	}
   546  
   547  	return haveIdenticalUnderlyingType(T, V, false)
   548  }
   549  
   550  func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
   551  	if T == V {
   552  		return true
   553  	}
   554  
   555  	kind := T.Kind()
   556  	if kind != V.Kind() {
   557  		return false
   558  	}
   559  
   560  	// Non-composite types of equal kind have same underlying type
   561  	// (the predefined instance of the type).
   562  	if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
   563  		return true
   564  	}
   565  
   566  	// Composite types.
   567  	switch kind {
   568  	case abi.Array:
   569  		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   570  
   571  	case abi.Chan:
   572  		// Special case:
   573  		// x is a bidirectional channel value, T is a channel type,
   574  		// and x's type V and T have identical element types.
   575  		if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
   576  			return true
   577  		}
   578  
   579  		// Otherwise continue test for identical underlying type.
   580  		return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   581  
   582  	case abi.Func:
   583  		t := (*funcType)(unsafe.Pointer(T))
   584  		v := (*funcType)(unsafe.Pointer(V))
   585  		if t.OutCount != v.OutCount || t.InCount != v.InCount {
   586  			return false
   587  		}
   588  		for i := 0; i < t.NumIn(); i++ {
   589  			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
   590  				return false
   591  			}
   592  		}
   593  		for i := 0; i < t.NumOut(); i++ {
   594  			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
   595  				return false
   596  			}
   597  		}
   598  		return true
   599  
   600  	case Interface:
   601  		t := (*interfaceType)(unsafe.Pointer(T))
   602  		v := (*interfaceType)(unsafe.Pointer(V))
   603  		if len(t.Methods) == 0 && len(v.Methods) == 0 {
   604  			return true
   605  		}
   606  		// Might have the same methods but still
   607  		// need a run time conversion.
   608  		return false
   609  
   610  	case abi.Map:
   611  		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   612  
   613  	case Ptr, abi.Slice:
   614  		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   615  
   616  	case abi.Struct:
   617  		t := (*structType)(unsafe.Pointer(T))
   618  		v := (*structType)(unsafe.Pointer(V))
   619  		if len(t.Fields) != len(v.Fields) {
   620  			return false
   621  		}
   622  		if t.PkgPath.Name() != v.PkgPath.Name() {
   623  			return false
   624  		}
   625  		for i := range t.Fields {
   626  			tf := &t.Fields[i]
   627  			vf := &v.Fields[i]
   628  			if tf.Name.Name() != vf.Name.Name() {
   629  				return false
   630  			}
   631  			if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
   632  				return false
   633  			}
   634  			if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
   635  				return false
   636  			}
   637  			if tf.Offset != vf.Offset {
   638  				return false
   639  			}
   640  			if tf.Embedded() != vf.Embedded() {
   641  				return false
   642  			}
   643  		}
   644  		return true
   645  	}
   646  
   647  	return false
   648  }
   649  
   650  // toType converts from a *rtype to a Type that can be returned
   651  // to the client of package reflect. In gc, the only concern is that
   652  // a nil *rtype must be replaced by a nil Type, but in gccgo this
   653  // function takes care of ensuring that multiple *rtype for the same
   654  // type are coalesced into a single Type.
   655  func toType(t *abi.Type) Type {
   656  	if t == nil {
   657  		return nil
   658  	}
   659  	return toRType(t)
   660  }
   661  
   662  // ifaceIndir reports whether t is stored indirectly in an interface value.
   663  func ifaceIndir(t *abi.Type) bool {
   664  	return t.Kind_&abi.KindDirectIface == 0
   665  }
   666  

View as plain text