github.com/AndrienkoAleksandr/go@v0.0.19/src/intern/reflectlite/type.go (about)

     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  	"github.com/AndrienkoAleksandr/go/src/intern/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  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
   237  
   238  // resolveTypeOff resolves an *rtype offset from a base type.
   239  // The (*rtype).typeOff method is a convenience wrapper for this function.
   240  // Implemented in the runtime package.
   241  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   242  
   243  func (t rtype) nameOff(off nameOff) abi.Name {
   244  	return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
   245  }
   246  
   247  func (t rtype) typeOff(off typeOff) *abi.Type {
   248  	return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
   249  }
   250  
   251  func (t rtype) uncommon() *uncommonType {
   252  	return t.Uncommon()
   253  }
   254  
   255  func (t rtype) String() string {
   256  	s := t.nameOff(t.Str).Name()
   257  	if t.TFlag&abi.TFlagExtraStar != 0 {
   258  		return s[1:]
   259  	}
   260  	return s
   261  }
   262  
   263  func (t rtype) common() *abi.Type { return t.Type }
   264  
   265  func (t rtype) exportedMethods() []abi.Method {
   266  	ut := t.uncommon()
   267  	if ut == nil {
   268  		return nil
   269  	}
   270  	return ut.ExportedMethods()
   271  }
   272  
   273  func (t rtype) NumMethod() int {
   274  	tt := t.Type.InterfaceType()
   275  	if tt != nil {
   276  		return tt.NumMethod()
   277  	}
   278  	return len(t.exportedMethods())
   279  }
   280  
   281  func (t rtype) PkgPath() string {
   282  	if t.TFlag&abi.TFlagNamed == 0 {
   283  		return ""
   284  	}
   285  	ut := t.uncommon()
   286  	if ut == nil {
   287  		return ""
   288  	}
   289  	return t.nameOff(ut.PkgPath).Name()
   290  }
   291  
   292  func (t rtype) Name() string {
   293  	if !t.HasName() {
   294  		return ""
   295  	}
   296  	s := t.String()
   297  	i := len(s) - 1
   298  	sqBrackets := 0
   299  	for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
   300  		switch s[i] {
   301  		case ']':
   302  			sqBrackets++
   303  		case '[':
   304  			sqBrackets--
   305  		}
   306  		i--
   307  	}
   308  	return s[i+1:]
   309  }
   310  
   311  func toRType(t *abi.Type) rtype {
   312  	return rtype{t}
   313  }
   314  
   315  func elem(t *abi.Type) *abi.Type {
   316  	et := t.Elem()
   317  	if et != nil {
   318  		return et
   319  	}
   320  	panic("reflect: Elem of invalid type " + toRType(t).String())
   321  }
   322  
   323  func (t rtype) Elem() Type {
   324  	return toType(elem(t.common()))
   325  }
   326  
   327  func (t rtype) In(i int) Type {
   328  	tt := t.Type.FuncType()
   329  	if tt == nil {
   330  		panic("reflect: In of non-func type")
   331  	}
   332  	return toType(tt.InSlice()[i])
   333  }
   334  
   335  func (t rtype) Key() Type {
   336  	tt := t.Type.MapType()
   337  	if tt == nil {
   338  		panic("reflect: Key of non-map type")
   339  	}
   340  	return toType(tt.Key)
   341  }
   342  
   343  func (t rtype) Len() int {
   344  	tt := t.Type.ArrayType()
   345  	if tt == nil {
   346  		panic("reflect: Len of non-array type")
   347  	}
   348  	return int(tt.Len)
   349  }
   350  
   351  func (t rtype) NumField() int {
   352  	tt := t.Type.StructType()
   353  	if tt == nil {
   354  		panic("reflect: NumField of non-struct type")
   355  	}
   356  	return len(tt.Fields)
   357  }
   358  
   359  func (t rtype) NumIn() int {
   360  	tt := t.Type.FuncType()
   361  	if tt == nil {
   362  		panic("reflect: NumIn of non-func type")
   363  	}
   364  	return int(tt.InCount)
   365  }
   366  
   367  func (t rtype) NumOut() int {
   368  	tt := t.Type.FuncType()
   369  	if tt == nil {
   370  		panic("reflect: NumOut of non-func type")
   371  	}
   372  	return tt.NumOut()
   373  }
   374  
   375  func (t rtype) Out(i int) Type {
   376  	tt := t.Type.FuncType()
   377  	if tt == nil {
   378  		panic("reflect: Out of non-func type")
   379  	}
   380  	return toType(tt.OutSlice()[i])
   381  }
   382  
   383  // add returns p+x.
   384  //
   385  // The whySafe string is ignored, so that the function still inlines
   386  // as efficiently as p+x, but all call sites should use the string to
   387  // record why the addition is safe, which is to say why the addition
   388  // does not cause x to advance to the very end of p's allocation
   389  // and therefore point incorrectly at the next block in memory.
   390  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   391  	return unsafe.Pointer(uintptr(p) + x)
   392  }
   393  
   394  // TypeOf returns the reflection Type that represents the dynamic type of i.
   395  // If i is a nil interface value, TypeOf returns nil.
   396  func TypeOf(i any) Type {
   397  	eface := *(*emptyInterface)(unsafe.Pointer(&i))
   398  	return toType(eface.typ)
   399  }
   400  
   401  func (t rtype) Implements(u Type) bool {
   402  	if u == nil {
   403  		panic("reflect: nil type passed to Type.Implements")
   404  	}
   405  	if u.Kind() != Interface {
   406  		panic("reflect: non-interface type passed to Type.Implements")
   407  	}
   408  	return implements(u.common(), t.common())
   409  }
   410  
   411  func (t rtype) AssignableTo(u Type) bool {
   412  	if u == nil {
   413  		panic("reflect: nil type passed to Type.AssignableTo")
   414  	}
   415  	uu := u.common()
   416  	tt := t.common()
   417  	return directlyAssignable(uu, tt) || implements(uu, tt)
   418  }
   419  
   420  func (t rtype) Comparable() bool {
   421  	return t.Equal != nil
   422  }
   423  
   424  // implements reports whether the type V implements the interface type T.
   425  func implements(T, V *abi.Type) bool {
   426  	t := T.InterfaceType()
   427  	if t == nil {
   428  		return false
   429  	}
   430  	if len(t.Methods) == 0 {
   431  		return true
   432  	}
   433  	rT := toRType(T)
   434  	rV := toRType(V)
   435  
   436  	// The same algorithm applies in both cases, but the
   437  	// method tables for an interface type and a concrete type
   438  	// are different, so the code is duplicated.
   439  	// In both cases the algorithm is a linear scan over the two
   440  	// lists - T's methods and V's methods - simultaneously.
   441  	// Since method tables are stored in a unique sorted order
   442  	// (alphabetical, with no duplicate method names), the scan
   443  	// through V's methods must hit a match for each of T's
   444  	// methods along the way, or else V does not implement T.
   445  	// This lets us run the scan in overall linear time instead of
   446  	// the quadratic time  a naive search would require.
   447  	// See also ../runtime/iface.go.
   448  	if V.Kind() == Interface {
   449  		v := (*interfaceType)(unsafe.Pointer(V))
   450  		i := 0
   451  		for j := 0; j < len(v.Methods); j++ {
   452  			tm := &t.Methods[i]
   453  			tmName := rT.nameOff(tm.Name)
   454  			vm := &v.Methods[j]
   455  			vmName := rV.nameOff(vm.Name)
   456  			if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
   457  				if !tmName.IsExported() {
   458  					tmPkgPath := pkgPath(tmName)
   459  					if tmPkgPath == "" {
   460  						tmPkgPath = t.PkgPath.Name()
   461  					}
   462  					vmPkgPath := pkgPath(vmName)
   463  					if vmPkgPath == "" {
   464  						vmPkgPath = v.PkgPath.Name()
   465  					}
   466  					if tmPkgPath != vmPkgPath {
   467  						continue
   468  					}
   469  				}
   470  				if i++; i >= len(t.Methods) {
   471  					return true
   472  				}
   473  			}
   474  		}
   475  		return false
   476  	}
   477  
   478  	v := V.Uncommon()
   479  	if v == nil {
   480  		return false
   481  	}
   482  	i := 0
   483  	vmethods := v.Methods()
   484  	for j := 0; j < int(v.Mcount); j++ {
   485  		tm := &t.Methods[i]
   486  		tmName := rT.nameOff(tm.Name)
   487  		vm := vmethods[j]
   488  		vmName := rV.nameOff(vm.Name)
   489  		if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
   490  			if !tmName.IsExported() {
   491  				tmPkgPath := pkgPath(tmName)
   492  				if tmPkgPath == "" {
   493  					tmPkgPath = t.PkgPath.Name()
   494  				}
   495  				vmPkgPath := pkgPath(vmName)
   496  				if vmPkgPath == "" {
   497  					vmPkgPath = rV.nameOff(v.PkgPath).Name()
   498  				}
   499  				if tmPkgPath != vmPkgPath {
   500  					continue
   501  				}
   502  			}
   503  			if i++; i >= len(t.Methods) {
   504  				return true
   505  			}
   506  		}
   507  	}
   508  	return false
   509  }
   510  
   511  // directlyAssignable reports whether a value x of type V can be directly
   512  // assigned (using memmove) to a value of type T.
   513  // https://golang.org/doc/go_spec.html#Assignability
   514  // Ignoring the interface rules (implemented elsewhere)
   515  // and the ideal constant rules (no ideal constants at run time).
   516  func directlyAssignable(T, V *abi.Type) bool {
   517  	// x's type V is identical to T?
   518  	if T == V {
   519  		return true
   520  	}
   521  
   522  	// Otherwise at least one of T and V must not be defined
   523  	// and they must have the same kind.
   524  	if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
   525  		return false
   526  	}
   527  
   528  	// x's type T and V must  have identical underlying types.
   529  	return haveIdenticalUnderlyingType(T, V, true)
   530  }
   531  
   532  func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
   533  	if cmpTags {
   534  		return T == V
   535  	}
   536  
   537  	if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
   538  		return false
   539  	}
   540  
   541  	return haveIdenticalUnderlyingType(T, V, false)
   542  }
   543  
   544  func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
   545  	if T == V {
   546  		return true
   547  	}
   548  
   549  	kind := T.Kind()
   550  	if kind != V.Kind() {
   551  		return false
   552  	}
   553  
   554  	// Non-composite types of equal kind have same underlying type
   555  	// (the predefined instance of the type).
   556  	if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
   557  		return true
   558  	}
   559  
   560  	// Composite types.
   561  	switch kind {
   562  	case abi.Array:
   563  		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   564  
   565  	case abi.Chan:
   566  		// Special case:
   567  		// x is a bidirectional channel value, T is a channel type,
   568  		// and x's type V and T have identical element types.
   569  		if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
   570  			return true
   571  		}
   572  
   573  		// Otherwise continue test for identical underlying type.
   574  		return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   575  
   576  	case abi.Func:
   577  		t := (*funcType)(unsafe.Pointer(T))
   578  		v := (*funcType)(unsafe.Pointer(V))
   579  		if t.OutCount != v.OutCount || t.InCount != v.InCount {
   580  			return false
   581  		}
   582  		for i := 0; i < t.NumIn(); i++ {
   583  			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
   584  				return false
   585  			}
   586  		}
   587  		for i := 0; i < t.NumOut(); i++ {
   588  			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
   589  				return false
   590  			}
   591  		}
   592  		return true
   593  
   594  	case Interface:
   595  		t := (*interfaceType)(unsafe.Pointer(T))
   596  		v := (*interfaceType)(unsafe.Pointer(V))
   597  		if len(t.Methods) == 0 && len(v.Methods) == 0 {
   598  			return true
   599  		}
   600  		// Might have the same methods but still
   601  		// need a run time conversion.
   602  		return false
   603  
   604  	case abi.Map:
   605  		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   606  
   607  	case Ptr, abi.Slice:
   608  		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   609  
   610  	case abi.Struct:
   611  		t := (*structType)(unsafe.Pointer(T))
   612  		v := (*structType)(unsafe.Pointer(V))
   613  		if len(t.Fields) != len(v.Fields) {
   614  			return false
   615  		}
   616  		if t.PkgPath.Name() != v.PkgPath.Name() {
   617  			return false
   618  		}
   619  		for i := range t.Fields {
   620  			tf := &t.Fields[i]
   621  			vf := &v.Fields[i]
   622  			if tf.Name.Name() != vf.Name.Name() {
   623  				return false
   624  			}
   625  			if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
   626  				return false
   627  			}
   628  			if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
   629  				return false
   630  			}
   631  			if tf.Offset != vf.Offset {
   632  				return false
   633  			}
   634  			if tf.Embedded() != vf.Embedded() {
   635  				return false
   636  			}
   637  		}
   638  		return true
   639  	}
   640  
   641  	return false
   642  }
   643  
   644  // toType converts from a *rtype to a Type that can be returned
   645  // to the client of package reflect. In gc, the only concern is that
   646  // a nil *rtype must be replaced by a nil Type, but in gccgo this
   647  // function takes care of ensuring that multiple *rtype for the same
   648  // type are coalesced into a single Type.
   649  func toType(t *abi.Type) Type {
   650  	if t == nil {
   651  		return nil
   652  	}
   653  	return toRType(t)
   654  }
   655  
   656  // ifaceIndir reports whether t is stored indirectly in an interface value.
   657  func ifaceIndir(t *abi.Type) bool {
   658  	return t.Kind_&abi.KindDirectIface == 0
   659  }