...

Source file src/internal/reflectlite/type.go

Documentation: internal/reflectlite

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package reflectlite implements lightweight version of reflect, not using
     6  // any package except for "runtime", "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  // ptrType represents a pointer type.
   115  type ptrType = abi.PtrType
   116  
   117  // sliceType represents a slice type.
   118  type sliceType = abi.SliceType
   119  
   120  // structType represents a struct type.
   121  type structType = abi.StructType
   122  
   123  // name is an encoded type name with optional extra data.
   124  //
   125  // The first byte is a bit field containing:
   126  //
   127  //	1<<0 the name is exported
   128  //	1<<1 tag data follows the name
   129  //	1<<2 pkgPath nameOff follows the name and tag
   130  //
   131  // The next two bytes are the data length:
   132  //
   133  //	l := uint16(data[1])<<8 | uint16(data[2])
   134  //
   135  // Bytes [3:3+l] are the string data.
   136  //
   137  // If tag data follows then bytes 3+l and 3+l+1 are the tag length,
   138  // with the data following.
   139  //
   140  // If the import path follows, then 4 bytes at the end of
   141  // the data form a nameOff. The import path is only set for concrete
   142  // methods that are defined in a different package than their type.
   143  //
   144  // If a name starts with "*", then the exported bit represents
   145  // whether the pointed to type is exported.
   146  type name struct {
   147  	bytes *byte
   148  }
   149  
   150  func (n name) data(off int, whySafe string) *byte {
   151  	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
   152  }
   153  
   154  func (n name) isExported() bool {
   155  	return (*n.bytes)&(1<<0) != 0
   156  }
   157  
   158  func (n name) hasTag() bool {
   159  	return (*n.bytes)&(1<<1) != 0
   160  }
   161  
   162  func (n name) embedded() bool {
   163  	return (*n.bytes)&(1<<3) != 0
   164  }
   165  
   166  // readVarint parses a varint as encoded by encoding/binary.
   167  // It returns the number of encoded bytes and the encoded value.
   168  func (n name) readVarint(off int) (int, int) {
   169  	v := 0
   170  	for i := 0; ; i++ {
   171  		x := *n.data(off+i, "read varint")
   172  		v += int(x&0x7f) << (7 * i)
   173  		if x&0x80 == 0 {
   174  			return i + 1, v
   175  		}
   176  	}
   177  }
   178  
   179  func (n name) name() string {
   180  	if n.bytes == nil {
   181  		return ""
   182  	}
   183  	i, l := n.readVarint(1)
   184  	return unsafe.String(n.data(1+i, "non-empty string"), l)
   185  }
   186  
   187  func (n name) tag() string {
   188  	if !n.hasTag() {
   189  		return ""
   190  	}
   191  	i, l := n.readVarint(1)
   192  	i2, l2 := n.readVarint(1 + i + l)
   193  	return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
   194  }
   195  
   196  func pkgPath(n abi.Name) string {
   197  	if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
   198  		return ""
   199  	}
   200  	i, l := n.ReadVarint(1)
   201  	off := 1 + i + l
   202  	if n.HasTag() {
   203  		i2, l2 := n.ReadVarint(off)
   204  		off += i2 + l2
   205  	}
   206  	var nameOff int32
   207  	// Note that this field may not be aligned in memory,
   208  	// so we cannot use a direct int32 assignment here.
   209  	copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
   210  	pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
   211  	return pkgPathName.name()
   212  }
   213  
   214  /*
   215   * The compiler knows the exact layout of all the data structures above.
   216   * The compiler does not know about the data structures and methods below.
   217   */
   218  
   219  // resolveNameOff resolves a name offset from a base pointer.
   220  // The (*rtype).nameOff method is a convenience wrapper for this function.
   221  // Implemented in the runtime package.
   222  //
   223  //go:noescape
   224  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
   225  
   226  // resolveTypeOff resolves an *rtype offset from a base type.
   227  // The (*rtype).typeOff method is a convenience wrapper for this function.
   228  // Implemented in the runtime package.
   229  //
   230  //go:noescape
   231  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   232  
   233  func (t rtype) nameOff(off nameOff) abi.Name {
   234  	return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
   235  }
   236  
   237  func (t rtype) typeOff(off typeOff) *abi.Type {
   238  	return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
   239  }
   240  
   241  func (t rtype) uncommon() *uncommonType {
   242  	return t.Uncommon()
   243  }
   244  
   245  func (t rtype) String() string {
   246  	s := t.nameOff(t.Str).Name()
   247  	if t.TFlag&abi.TFlagExtraStar != 0 {
   248  		return s[1:]
   249  	}
   250  	return s
   251  }
   252  
   253  func (t rtype) common() *abi.Type { return t.Type }
   254  
   255  func (t rtype) exportedMethods() []abi.Method {
   256  	ut := t.uncommon()
   257  	if ut == nil {
   258  		return nil
   259  	}
   260  	return ut.ExportedMethods()
   261  }
   262  
   263  func (t rtype) NumMethod() int {
   264  	tt := t.Type.InterfaceType()
   265  	if tt != nil {
   266  		return tt.NumMethod()
   267  	}
   268  	return len(t.exportedMethods())
   269  }
   270  
   271  func (t rtype) PkgPath() string {
   272  	if t.TFlag&abi.TFlagNamed == 0 {
   273  		return ""
   274  	}
   275  	ut := t.uncommon()
   276  	if ut == nil {
   277  		return ""
   278  	}
   279  	return t.nameOff(ut.PkgPath).Name()
   280  }
   281  
   282  func (t rtype) Name() string {
   283  	if !t.HasName() {
   284  		return ""
   285  	}
   286  	s := t.String()
   287  	i := len(s) - 1
   288  	sqBrackets := 0
   289  	for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
   290  		switch s[i] {
   291  		case ']':
   292  			sqBrackets++
   293  		case '[':
   294  			sqBrackets--
   295  		}
   296  		i--
   297  	}
   298  	return s[i+1:]
   299  }
   300  
   301  func toRType(t *abi.Type) rtype {
   302  	return rtype{t}
   303  }
   304  
   305  func elem(t *abi.Type) *abi.Type {
   306  	et := t.Elem()
   307  	if et != nil {
   308  		return et
   309  	}
   310  	panic("reflect: Elem of invalid type " + toRType(t).String())
   311  }
   312  
   313  func (t rtype) Elem() Type {
   314  	return toType(elem(t.common()))
   315  }
   316  
   317  func (t rtype) In(i int) Type {
   318  	tt := t.Type.FuncType()
   319  	if tt == nil {
   320  		panic("reflect: In of non-func type")
   321  	}
   322  	return toType(tt.InSlice()[i])
   323  }
   324  
   325  func (t rtype) Key() Type {
   326  	tt := t.Type.MapType()
   327  	if tt == nil {
   328  		panic("reflect: Key of non-map type")
   329  	}
   330  	return toType(tt.Key)
   331  }
   332  
   333  func (t rtype) Len() int {
   334  	tt := t.Type.ArrayType()
   335  	if tt == nil {
   336  		panic("reflect: Len of non-array type")
   337  	}
   338  	return int(tt.Len)
   339  }
   340  
   341  func (t rtype) NumField() int {
   342  	tt := t.Type.StructType()
   343  	if tt == nil {
   344  		panic("reflect: NumField of non-struct type")
   345  	}
   346  	return len(tt.Fields)
   347  }
   348  
   349  func (t rtype) NumIn() int {
   350  	tt := t.Type.FuncType()
   351  	if tt == nil {
   352  		panic("reflect: NumIn of non-func type")
   353  	}
   354  	return int(tt.InCount)
   355  }
   356  
   357  func (t rtype) NumOut() int {
   358  	tt := t.Type.FuncType()
   359  	if tt == nil {
   360  		panic("reflect: NumOut of non-func type")
   361  	}
   362  	return tt.NumOut()
   363  }
   364  
   365  func (t rtype) Out(i int) Type {
   366  	tt := t.Type.FuncType()
   367  	if tt == nil {
   368  		panic("reflect: Out of non-func type")
   369  	}
   370  	return toType(tt.OutSlice()[i])
   371  }
   372  
   373  // add returns p+x.
   374  //
   375  // The whySafe string is ignored, so that the function still inlines
   376  // as efficiently as p+x, but all call sites should use the string to
   377  // record why the addition is safe, which is to say why the addition
   378  // does not cause x to advance to the very end of p's allocation
   379  // and therefore point incorrectly at the next block in memory.
   380  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   381  	return unsafe.Pointer(uintptr(p) + x)
   382  }
   383  
   384  // TypeOf returns the reflection Type that represents the dynamic type of i.
   385  // If i is a nil interface value, TypeOf returns nil.
   386  func TypeOf(i any) Type {
   387  	return toType(abi.TypeOf(i))
   388  }
   389  
   390  func (t rtype) Implements(u Type) bool {
   391  	if u == nil {
   392  		panic("reflect: nil type passed to Type.Implements")
   393  	}
   394  	if u.Kind() != Interface {
   395  		panic("reflect: non-interface type passed to Type.Implements")
   396  	}
   397  	return implements(u.common(), t.common())
   398  }
   399  
   400  func (t rtype) AssignableTo(u Type) bool {
   401  	if u == nil {
   402  		panic("reflect: nil type passed to Type.AssignableTo")
   403  	}
   404  	uu := u.common()
   405  	tt := t.common()
   406  	return directlyAssignable(uu, tt) || implements(uu, tt)
   407  }
   408  
   409  func (t rtype) Comparable() bool {
   410  	return t.Equal != nil
   411  }
   412  
   413  // implements reports whether the type V implements the interface type T.
   414  func implements(T, V *abi.Type) bool {
   415  	t := T.InterfaceType()
   416  	if t == nil {
   417  		return false
   418  	}
   419  	if len(t.Methods) == 0 {
   420  		return true
   421  	}
   422  	rT := toRType(T)
   423  	rV := toRType(V)
   424  
   425  	// The same algorithm applies in both cases, but the
   426  	// method tables for an interface type and a concrete type
   427  	// are different, so the code is duplicated.
   428  	// In both cases the algorithm is a linear scan over the two
   429  	// lists - T's methods and V's methods - simultaneously.
   430  	// Since method tables are stored in a unique sorted order
   431  	// (alphabetical, with no duplicate method names), the scan
   432  	// through V's methods must hit a match for each of T's
   433  	// methods along the way, or else V does not implement T.
   434  	// This lets us run the scan in overall linear time instead of
   435  	// the quadratic time  a naive search would require.
   436  	// See also ../runtime/iface.go.
   437  	if V.Kind() == Interface {
   438  		v := (*interfaceType)(unsafe.Pointer(V))
   439  		i := 0
   440  		for j := 0; j < len(v.Methods); j++ {
   441  			tm := &t.Methods[i]
   442  			tmName := rT.nameOff(tm.Name)
   443  			vm := &v.Methods[j]
   444  			vmName := rV.nameOff(vm.Name)
   445  			if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
   446  				if !tmName.IsExported() {
   447  					tmPkgPath := pkgPath(tmName)
   448  					if tmPkgPath == "" {
   449  						tmPkgPath = t.PkgPath.Name()
   450  					}
   451  					vmPkgPath := pkgPath(vmName)
   452  					if vmPkgPath == "" {
   453  						vmPkgPath = v.PkgPath.Name()
   454  					}
   455  					if tmPkgPath != vmPkgPath {
   456  						continue
   457  					}
   458  				}
   459  				if i++; i >= len(t.Methods) {
   460  					return true
   461  				}
   462  			}
   463  		}
   464  		return false
   465  	}
   466  
   467  	v := V.Uncommon()
   468  	if v == nil {
   469  		return false
   470  	}
   471  	i := 0
   472  	vmethods := v.Methods()
   473  	for j := 0; j < int(v.Mcount); j++ {
   474  		tm := &t.Methods[i]
   475  		tmName := rT.nameOff(tm.Name)
   476  		vm := vmethods[j]
   477  		vmName := rV.nameOff(vm.Name)
   478  		if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
   479  			if !tmName.IsExported() {
   480  				tmPkgPath := pkgPath(tmName)
   481  				if tmPkgPath == "" {
   482  					tmPkgPath = t.PkgPath.Name()
   483  				}
   484  				vmPkgPath := pkgPath(vmName)
   485  				if vmPkgPath == "" {
   486  					vmPkgPath = rV.nameOff(v.PkgPath).Name()
   487  				}
   488  				if tmPkgPath != vmPkgPath {
   489  					continue
   490  				}
   491  			}
   492  			if i++; i >= len(t.Methods) {
   493  				return true
   494  			}
   495  		}
   496  	}
   497  	return false
   498  }
   499  
   500  // directlyAssignable reports whether a value x of type V can be directly
   501  // assigned (using memmove) to a value of type T.
   502  // https://golang.org/doc/go_spec.html#Assignability
   503  // Ignoring the interface rules (implemented elsewhere)
   504  // and the ideal constant rules (no ideal constants at run time).
   505  func directlyAssignable(T, V *abi.Type) bool {
   506  	// x's type V is identical to T?
   507  	if T == V {
   508  		return true
   509  	}
   510  
   511  	// Otherwise at least one of T and V must not be defined
   512  	// and they must have the same kind.
   513  	if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
   514  		return false
   515  	}
   516  
   517  	// x's type T and V must  have identical underlying types.
   518  	return haveIdenticalUnderlyingType(T, V, true)
   519  }
   520  
   521  func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
   522  	if cmpTags {
   523  		return T == V
   524  	}
   525  
   526  	if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
   527  		return false
   528  	}
   529  
   530  	return haveIdenticalUnderlyingType(T, V, false)
   531  }
   532  
   533  func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
   534  	if T == V {
   535  		return true
   536  	}
   537  
   538  	kind := T.Kind()
   539  	if kind != V.Kind() {
   540  		return false
   541  	}
   542  
   543  	// Non-composite types of equal kind have same underlying type
   544  	// (the predefined instance of the type).
   545  	if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
   546  		return true
   547  	}
   548  
   549  	// Composite types.
   550  	switch kind {
   551  	case abi.Array:
   552  		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   553  
   554  	case abi.Chan:
   555  		// Special case:
   556  		// x is a bidirectional channel value, T is a channel type,
   557  		// and x's type V and T have identical element types.
   558  		if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
   559  			return true
   560  		}
   561  
   562  		// Otherwise continue test for identical underlying type.
   563  		return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   564  
   565  	case abi.Func:
   566  		t := (*funcType)(unsafe.Pointer(T))
   567  		v := (*funcType)(unsafe.Pointer(V))
   568  		if t.OutCount != v.OutCount || t.InCount != v.InCount {
   569  			return false
   570  		}
   571  		for i := 0; i < t.NumIn(); i++ {
   572  			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
   573  				return false
   574  			}
   575  		}
   576  		for i := 0; i < t.NumOut(); i++ {
   577  			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
   578  				return false
   579  			}
   580  		}
   581  		return true
   582  
   583  	case Interface:
   584  		t := (*interfaceType)(unsafe.Pointer(T))
   585  		v := (*interfaceType)(unsafe.Pointer(V))
   586  		if len(t.Methods) == 0 && len(v.Methods) == 0 {
   587  			return true
   588  		}
   589  		// Might have the same methods but still
   590  		// need a run time conversion.
   591  		return false
   592  
   593  	case abi.Map:
   594  		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   595  
   596  	case Ptr, abi.Slice:
   597  		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
   598  
   599  	case abi.Struct:
   600  		t := (*structType)(unsafe.Pointer(T))
   601  		v := (*structType)(unsafe.Pointer(V))
   602  		if len(t.Fields) != len(v.Fields) {
   603  			return false
   604  		}
   605  		if t.PkgPath.Name() != v.PkgPath.Name() {
   606  			return false
   607  		}
   608  		for i := range t.Fields {
   609  			tf := &t.Fields[i]
   610  			vf := &v.Fields[i]
   611  			if tf.Name.Name() != vf.Name.Name() {
   612  				return false
   613  			}
   614  			if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
   615  				return false
   616  			}
   617  			if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
   618  				return false
   619  			}
   620  			if tf.Offset != vf.Offset {
   621  				return false
   622  			}
   623  			if tf.Embedded() != vf.Embedded() {
   624  				return false
   625  			}
   626  		}
   627  		return true
   628  	}
   629  
   630  	return false
   631  }
   632  
   633  // toType converts from a *rtype to a Type that can be returned
   634  // to the client of package reflect. In gc, the only concern is that
   635  // a nil *rtype must be replaced by a nil Type, but in gccgo this
   636  // function takes care of ensuring that multiple *rtype for the same
   637  // type are coalesced into a single Type.
   638  func toType(t *abi.Type) Type {
   639  	if t == nil {
   640  		return nil
   641  	}
   642  	return toRType(t)
   643  }
   644  

View as plain text