...

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

View as plain text