github.com/goplusjs/reflectx@v0.5.4/rtype.go (about)

     1  //go:build !js || (js && wasm)
     2  // +build !js js,wasm
     3  
     4  package reflectx
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"reflect"
    10  	"unsafe"
    11  )
    12  
    13  func toStructType(t *rtype) *structType {
    14  	return (*structType)(unsafe.Pointer(t))
    15  }
    16  
    17  func toKindType(t *rtype) unsafe.Pointer {
    18  	return unsafe.Pointer(t)
    19  }
    20  
    21  func toUncommonType(t *rtype) *uncommonType {
    22  	if t.tflag&tflagUncommon == 0 {
    23  		return nil
    24  	}
    25  	switch t.Kind() {
    26  	case reflect.Struct:
    27  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
    28  	case reflect.Ptr:
    29  		type u struct {
    30  			ptrType
    31  			u uncommonType
    32  		}
    33  		return &(*u)(unsafe.Pointer(t)).u
    34  	case reflect.Func:
    35  		type u struct {
    36  			funcType
    37  			u uncommonType
    38  		}
    39  		return &(*u)(unsafe.Pointer(t)).u
    40  	case reflect.Slice:
    41  		type u struct {
    42  			sliceType
    43  			u uncommonType
    44  		}
    45  		return &(*u)(unsafe.Pointer(t)).u
    46  	case reflect.Array:
    47  		type u struct {
    48  			arrayType
    49  			u uncommonType
    50  		}
    51  		return &(*u)(unsafe.Pointer(t)).u
    52  	case reflect.Chan:
    53  		type u struct {
    54  			chanType
    55  			u uncommonType
    56  		}
    57  		return &(*u)(unsafe.Pointer(t)).u
    58  	case reflect.Map:
    59  		type u struct {
    60  			mapType
    61  			u uncommonType
    62  		}
    63  		return &(*u)(unsafe.Pointer(t)).u
    64  	case reflect.Interface:
    65  		type u struct {
    66  			interfaceType
    67  			u uncommonType
    68  		}
    69  		return &(*u)(unsafe.Pointer(t)).u
    70  	default:
    71  		type u struct {
    72  			rtype
    73  			u uncommonType
    74  		}
    75  		return &(*u)(unsafe.Pointer(t)).u
    76  	}
    77  }
    78  
    79  // uncommonType is present only for defined types or types with methods
    80  // (if T is a defined type, the uncommonTypes for T and *T have methods).
    81  // Using a pointer to this struct reduces the overall size required
    82  // to describe a non-defined type with no methods.
    83  type uncommonType struct {
    84  	pkgPath nameOff // import path; empty for built-in types like int, string
    85  	mcount  uint16  // number of methods
    86  	xcount  uint16  // number of exported methods
    87  	moff    uint32  // offset from this uncommontype to [mcount]method
    88  	_       uint32  // unused
    89  }
    90  
    91  type funcTypeFixed1 struct {
    92  	funcType
    93  	args [1]*rtype
    94  }
    95  
    96  type funcTypeFixed4 struct {
    97  	funcType
    98  	args [4]*rtype
    99  }
   100  type funcTypeFixed8 struct {
   101  	funcType
   102  	args [8]*rtype
   103  }
   104  type funcTypeFixed16 struct {
   105  	funcType
   106  	args [16]*rtype
   107  }
   108  type funcTypeFixed32 struct {
   109  	funcType
   110  	args [32]*rtype
   111  }
   112  type funcTypeFixed64 struct {
   113  	funcType
   114  	args [64]*rtype
   115  }
   116  type funcTypeFixed128 struct {
   117  	funcType
   118  	args [128]*rtype
   119  }
   120  
   121  // emptyInterface is the header for an interface{} value.
   122  type emptyInterface struct {
   123  	typ  *rtype
   124  	word unsafe.Pointer
   125  }
   126  
   127  func totype(typ reflect.Type) *rtype {
   128  	e := (*emptyInterface)(unsafe.Pointer(&typ))
   129  	return (*rtype)(e.word)
   130  }
   131  
   132  //go:nocheckptr
   133  func (t *uncommonType) methods() []method {
   134  	if t == nil || t.mcount == 0 {
   135  		return nil
   136  	}
   137  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
   138  }
   139  
   140  //go:nocheckptr
   141  func (t *uncommonType) exportedMethods() []method {
   142  	if t == nil || t.xcount == 0 {
   143  		return nil
   144  	}
   145  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
   146  }
   147  
   148  func tovalue(v *reflect.Value) *Value {
   149  	return (*Value)(unsafe.Pointer(v))
   150  }
   151  
   152  func toValue(v Value) reflect.Value {
   153  	return *(*reflect.Value)(unsafe.Pointer(&v))
   154  }
   155  
   156  func (t *rtype) uncommon() *uncommonType {
   157  	return toUncommonType(t)
   158  }
   159  
   160  func (t *rtype) exportedMethods() []method {
   161  	ut := t.uncommon()
   162  	if ut == nil {
   163  		return nil
   164  	}
   165  	return ut.exportedMethods()
   166  }
   167  
   168  func (t *rtype) methods() []method {
   169  	ut := t.uncommon()
   170  	if ut == nil {
   171  		return nil
   172  	}
   173  	return ut.methods()
   174  }
   175  
   176  func (t *funcType) in() []*rtype {
   177  	uadd := unsafe.Sizeof(*t)
   178  	if t.tflag&tflagUncommon != 0 {
   179  		uadd += unsafe.Sizeof(uncommonType{})
   180  	}
   181  	if t.inCount == 0 {
   182  		return nil
   183  	}
   184  	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
   185  }
   186  
   187  func (t *funcType) out() []*rtype {
   188  	uadd := unsafe.Sizeof(*t)
   189  	if t.tflag&tflagUncommon != 0 {
   190  		uadd += unsafe.Sizeof(uncommonType{})
   191  	}
   192  	outCount := t.outCount & (1<<15 - 1)
   193  	if outCount == 0 {
   194  		return nil
   195  	}
   196  	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
   197  }
   198  
   199  func (t *rtype) IsVariadic() bool {
   200  	if t.Kind() != reflect.Func {
   201  		panic("reflect: IsVariadic of non-func type " + toType(t).String())
   202  	}
   203  	tt := (*funcType)(unsafe.Pointer(t))
   204  	return tt.outCount&(1<<15) != 0
   205  }
   206  
   207  // func (t *_rtype) nameOff(off nameOff) name {
   208  // 	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
   209  // }
   210  
   211  type makeFuncImpl struct {
   212  	code   uintptr
   213  	stack  *bitVector // ptrmap for both args and results
   214  	argLen uintptr    // just args
   215  	ftyp   *funcType
   216  	fn     func([]reflect.Value) []reflect.Value
   217  }
   218  
   219  type bitVector struct {
   220  	n    uint32 // number of bits
   221  	data []byte
   222  }
   223  
   224  // funcType represents a function type.
   225  //
   226  // A *rtype for each in and out parameter is stored in an array that
   227  // directly follows the funcType (and possibly its uncommonType). So
   228  // a function type with one method, one input, and one output is:
   229  //
   230  //	struct {
   231  //		funcType
   232  //		uncommonType
   233  //		[2]*rtype    // [0] is in, [1] is out
   234  //	}
   235  type funcType struct {
   236  	rtype
   237  	inCount  uint16
   238  	outCount uint16 // top bit is set if last input parameter is ...
   239  }
   240  
   241  type offFuncType struct {
   242  	funcType
   243  	uncommonType
   244  	args [128]*rtype
   245  }
   246  
   247  func SetUnderlying(typ reflect.Type, styp reflect.Type) {
   248  	rt := totype(typ)
   249  	ort := totype(styp)
   250  	switch styp.Kind() {
   251  	case reflect.Struct:
   252  		st := (*structType)(unsafe.Pointer(rt))
   253  		ost := (*structType)(unsafe.Pointer(ort))
   254  		st.fields = ost.fields
   255  	case reflect.Ptr:
   256  		st := (*ptrType)(unsafe.Pointer(rt))
   257  		ost := (*ptrType)(unsafe.Pointer(ort))
   258  		st.elem = ost.elem
   259  	case reflect.Slice:
   260  		st := (*sliceType)(unsafe.Pointer(rt))
   261  		ost := (*sliceType)(unsafe.Pointer(ort))
   262  		st.elem = ost.elem
   263  	case reflect.Array:
   264  		st := (*arrayType)(unsafe.Pointer(rt))
   265  		ost := (*arrayType)(unsafe.Pointer(ort))
   266  		st.elem = ost.elem
   267  		st.slice = ost.slice
   268  		st.len = ost.len
   269  	case reflect.Chan:
   270  		st := (*chanType)(unsafe.Pointer(rt))
   271  		ost := (*chanType)(unsafe.Pointer(ort))
   272  		st.elem = ost.elem
   273  		st.dir = ost.dir
   274  	case reflect.Interface:
   275  		st := (*interfaceType)(unsafe.Pointer(rt))
   276  		ost := (*interfaceType)(unsafe.Pointer(ort))
   277  		st.methods = ost.methods
   278  	case reflect.Map:
   279  		st := (*mapType)(unsafe.Pointer(rt))
   280  		ost := (*mapType)(unsafe.Pointer(ort))
   281  		st.key = ost.key
   282  		st.elem = ost.elem
   283  		st.bucket = ost.bucket
   284  		st.hasher = ost.hasher
   285  		st.keysize = ost.keysize
   286  		st.valuesize = ost.valuesize
   287  		st.bucketsize = ost.bucketsize
   288  		st.flags = ost.flags
   289  	case reflect.Func:
   290  		st := (*funcType)(unsafe.Pointer(rt))
   291  		ost := (*funcType)(unsafe.Pointer(ort))
   292  		st.inCount = ost.inCount
   293  		st.outCount = ost.outCount
   294  		narg := ost.inCount + ost.outCount
   295  		if narg > 0 {
   296  			args := make([]*rtype, narg, narg)
   297  			for i := 0; i < styp.NumIn(); i++ {
   298  				args[i] = totype(styp.In(i))
   299  			}
   300  			index := styp.NumIn()
   301  			for i := 0; i < styp.NumOut(); i++ {
   302  				args[index+i] = totype(styp.Out(i))
   303  			}
   304  			dst := (*offFuncType)(unsafe.Pointer(rt))
   305  			for i, a := range args {
   306  				dst.args[i] = a
   307  			}
   308  		}
   309  	}
   310  	rt.size = ort.size
   311  	rt.tflag |= tflagUncommon | tflagExtraStar | tflagNamed
   312  	rt.kind = ort.kind
   313  	rt.align = ort.align
   314  	rt.fieldAlign = ort.fieldAlign
   315  	rt.gcdata = ort.gcdata
   316  	rt.ptrdata = ort.ptrdata
   317  	rt.equal = ort.equal
   318  	//rt.str = resolveReflectName(ort.nameOff(ort.str))
   319  	if isRegularMemory(typ) {
   320  		rt.tflag |= tflagRegularMemory
   321  	}
   322  }
   323  
   324  func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) (*rtype, []method) {
   325  	var rt *rtype
   326  	var fnoff uint32
   327  	var tt reflect.Value
   328  	ort := totype(styp)
   329  	skind := styp.Kind()
   330  	switch skind {
   331  	case reflect.Struct:
   332  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   333  			{Name: "S", Type: reflect.TypeOf(structType{})},
   334  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   335  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   336  		}))
   337  		st := (*structType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   338  		ost := (*structType)(unsafe.Pointer(ort))
   339  		st.fields = ost.fields
   340  	case reflect.Ptr:
   341  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   342  			{Name: "S", Type: reflect.TypeOf(ptrType{})},
   343  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   344  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   345  		}))
   346  		st := (*ptrType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   347  		st.elem = totype(styp.Elem())
   348  	case reflect.Interface:
   349  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   350  			{Name: "S", Type: reflect.TypeOf(interfaceType{})},
   351  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   352  		}))
   353  		st := (*interfaceType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   354  		ost := (*interfaceType)(unsafe.Pointer(ort))
   355  		for _, m := range ost.methods {
   356  			st.methods = append(st.methods, imethod{
   357  				name: resolveReflectName(ost.nameOff(m.name)),
   358  				typ:  resolveReflectType(ost.typeOff(m.typ)),
   359  			})
   360  		}
   361  	case reflect.Slice:
   362  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   363  			{Name: "S", Type: reflect.TypeOf(sliceType{})},
   364  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   365  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   366  		}))
   367  		st := (*sliceType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   368  		st.elem = totype(styp.Elem())
   369  	case reflect.Array:
   370  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   371  			{Name: "S", Type: reflect.TypeOf(arrayType{})},
   372  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   373  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   374  		}))
   375  		st := (*arrayType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   376  		ost := (*arrayType)(unsafe.Pointer(ort))
   377  		st.elem = ost.elem
   378  		st.slice = ost.slice
   379  		st.len = ost.len
   380  	case reflect.Chan:
   381  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   382  			{Name: "S", Type: reflect.TypeOf(chanType{})},
   383  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   384  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   385  		}))
   386  		st := (*chanType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   387  		ost := (*chanType)(unsafe.Pointer(ort))
   388  		st.elem = ost.elem
   389  		st.dir = ost.dir
   390  	case reflect.Func:
   391  		narg := styp.NumIn() + styp.NumOut()
   392  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   393  			{Name: "S", Type: reflect.TypeOf(funcType{})},
   394  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   395  			{Name: "N", Type: reflect.ArrayOf(narg, reflect.TypeOf((*rtype)(nil)))},
   396  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   397  		}))
   398  		st := (*funcType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   399  		ost := (*funcType)(unsafe.Pointer(ort))
   400  		st.inCount = ost.inCount
   401  		st.outCount = ost.outCount
   402  		if narg > 0 {
   403  			args := make([]*rtype, narg, narg)
   404  			fnoff = uint32(unsafe.Sizeof((*rtype)(nil))) * uint32(narg)
   405  			for i := 0; i < styp.NumIn(); i++ {
   406  				args[i] = totype(styp.In(i))
   407  			}
   408  			index := styp.NumIn()
   409  			for i := 0; i < styp.NumOut(); i++ {
   410  				args[index+i] = totype(styp.Out(i))
   411  			}
   412  			copy(tt.Elem().Field(2).Slice(0, narg).Interface().([]*rtype), args)
   413  		}
   414  	case reflect.Map:
   415  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   416  			{Name: "S", Type: reflect.TypeOf(mapType{})},
   417  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   418  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   419  		}))
   420  		st := (*mapType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   421  		ost := (*mapType)(unsafe.Pointer(ort))
   422  		st.key = ost.key
   423  		st.elem = ost.elem
   424  		st.bucket = ost.bucket
   425  		st.hasher = ost.hasher
   426  		st.keysize = ost.keysize
   427  		st.valuesize = ost.valuesize
   428  		st.bucketsize = ost.bucketsize
   429  		st.flags = ost.flags
   430  	default:
   431  		tt = reflect.New(reflect.StructOf([]reflect.StructField{
   432  			{Name: "S", Type: reflect.TypeOf(rtype{})},
   433  			{Name: "U", Type: reflect.TypeOf(uncommonType{})},
   434  			{Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))},
   435  		}))
   436  	}
   437  	rt = (*rtype)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
   438  	rt.size = ort.size
   439  	rt.tflag = ort.tflag | tflagUncommon
   440  	rt.kind = ort.kind
   441  	rt.align = ort.align
   442  	rt.fieldAlign = ort.fieldAlign
   443  	rt.gcdata = ort.gcdata
   444  	rt.ptrdata = ort.ptrdata
   445  	rt.equal = ort.equal
   446  	rt.str = resolveReflectName(ort.nameOff(ort.str))
   447  	ut := (*uncommonType)(unsafe.Pointer(tt.Elem().Field(1).UnsafeAddr()))
   448  	ut.mcount = uint16(mcount)
   449  	ut.xcount = uint16(xcount)
   450  	ut.moff = uint32(unsafe.Sizeof(uncommonType{}))
   451  	if skind == reflect.Interface {
   452  		return rt, nil
   453  	} else if skind == reflect.Func {
   454  		ut.moff += fnoff
   455  		return rt, tt.Elem().Field(3).Slice(0, mcount).Interface().([]method)
   456  	}
   457  	return rt, tt.Elem().Field(2).Slice(0, mcount).Interface().([]method)
   458  }
   459  
   460  func NamedTypeOf(pkgpath string, name string, from reflect.Type) reflect.Type {
   461  	rt, _ := newType(pkgpath, name, from, 0, 0)
   462  	setTypeName(rt, pkgpath, name)
   463  	typ := toType(rt)
   464  	ntypeMap[typ] = &Named{Name: name, PkgPath: pkgpath, Type: typ, From: from, Kind: TkType}
   465  	return typ
   466  }
   467  
   468  //go:linkname typesByString reflect.typesByString
   469  func typesByString(s string) []*rtype
   470  
   471  //go:linkname typelinks reflect.typelinks
   472  func typelinks() (sections []unsafe.Pointer, offset [][]int32)
   473  
   474  //go:linkname rtypeOff reflect.rtypeOff
   475  func rtypeOff(section unsafe.Pointer, off int32) *rtype
   476  
   477  //go:linkname haveIdenticalUnderlyingType reflect.haveIdenticalUnderlyingType
   478  func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool
   479  
   480  func TypeLinks() []reflect.Type {
   481  	var r []reflect.Type
   482  	sections, offset := typelinks()
   483  	for i, offs := range offset {
   484  		rodata := sections[i]
   485  		for _, off := range offs {
   486  			typ := (*rtype)(resolveTypeOff(unsafe.Pointer(rodata), off))
   487  			r = append(r, toType(typ))
   488  		}
   489  	}
   490  	return r
   491  }
   492  
   493  func TypesByString(s string) []reflect.Type {
   494  	sections, offset := typelinks()
   495  	var ret []reflect.Type
   496  
   497  	for offsI, offs := range offset {
   498  		section := sections[offsI]
   499  
   500  		// We are looking for the first index i where the string becomes >= s.
   501  		// This is a copy of sort.Search, with f(h) replaced by (*typ[h].String() >= s).
   502  		i, j := 0, len(offs)
   503  		for i < j {
   504  			h := i + (j-i)/2 // avoid overflow when computing h
   505  			// i ≤ h < j
   506  			typ := toType(rtypeOff(section, offs[h]))
   507  			if !(typ.String() >= s) {
   508  				i = h + 1 // preserves f(i-1) == false
   509  			} else {
   510  				j = h // preserves f(j) == true
   511  			}
   512  		}
   513  		// i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
   514  
   515  		// Having found the first, linear scan forward to find the last.
   516  		// We could do a second binary search, but the caller is going
   517  		// to do a linear scan anyway.
   518  		for j := i; j < len(offs); j++ {
   519  			typ := toType(rtypeOff(section, offs[j]))
   520  			if typ.String() != s {
   521  				break
   522  			}
   523  			ret = append(ret, typ)
   524  		}
   525  	}
   526  	return ret
   527  }
   528  
   529  func DumpType(w io.Writer, typ reflect.Type) {
   530  	rt := totype(typ)
   531  	fmt.Fprintf(w, "%#v\n", rt)
   532  	for _, m := range rt.methods() {
   533  		fmt.Fprintf(w, "%v %v (%v)\t\t%#v\n",
   534  			rt.nameOff(m.name).name(),
   535  			rt.nameOff(m.name).pkgPath(),
   536  			toType(rt.typeOff(m.mtyp)),
   537  			m)
   538  	}
   539  }
   540  
   541  // func Implements(T reflect.Type, U reflect.Type) bool {
   542  // 	return implements(totype(T), totype(U))
   543  // }
   544  
   545  // // implements reports whether the type V implements the interface type T.
   546  // func implements(T, V *_rtype) bool {
   547  // 	if T.Kind() != reflect.Interface {
   548  // 		return false
   549  // 	}
   550  // 	t := (*interfaceType)(unsafe.Pointer(T))
   551  // 	if len(t.methods) == 0 {
   552  // 		return true
   553  // 	}
   554  
   555  // 	// The same algorithm applies in both cases, but the
   556  // 	// method tables for an interface type and a concrete type
   557  // 	// are different, so the code is duplicated.
   558  // 	// In both cases the algorithm is a linear scan over the two
   559  // 	// lists - T's methods and V's methods - simultaneously.
   560  // 	// Since method tables are stored in a unique sorted order
   561  // 	// (alphabetical, with no duplicate method names), the scan
   562  // 	// through V's methods must hit a match for each of T's
   563  // 	// methods along the way, or else V does not implement T.
   564  // 	// This lets us run the scan in overall linear time instead of
   565  // 	// the quadratic time  a naive search would require.
   566  // 	// See also ../runtime/iface.go.
   567  // 	if V.Kind() == reflect.Interface {
   568  // 		v := (*interfaceType)(unsafe.Pointer(V))
   569  // 		i := 0
   570  // 		for j := 0; j < len(v.methods); j++ {
   571  // 			tm := &t.methods[i]
   572  // 			tmName := t.nameOff(tm.name)
   573  // 			vm := &v.methods[j]
   574  // 			vmName := V.nameOff(vm.name)
   575  // 			if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
   576  // 				if !tmName.isExported() {
   577  // 					tmPkgPath := tmName.pkgPath()
   578  // 					if tmPkgPath == "" {
   579  // 						tmPkgPath = t.pkgPath.name()
   580  // 					}
   581  // 					vmPkgPath := vmName.pkgPath()
   582  // 					if vmPkgPath == "" {
   583  // 						vmPkgPath = v.pkgPath.name()
   584  // 					}
   585  // 					if tmPkgPath != vmPkgPath {
   586  // 						continue
   587  // 					}
   588  // 				}
   589  // 				if i++; i >= len(t.methods) {
   590  // 					return true
   591  // 				}
   592  // 			}
   593  // 		}
   594  // 		return false
   595  // 	}
   596  
   597  // 	v := V.uncommon()
   598  // 	if v == nil {
   599  // 		return false
   600  // 	}
   601  // 	i := 0
   602  // 	vmethods := v.methods()
   603  // 	for j := 0; j < int(v.mcount); j++ {
   604  // 		tm := &t.methods[i]
   605  // 		tmName := t.nameOff(tm.name)
   606  // 		vm := vmethods[j]
   607  // 		vmName := V.nameOff(vm.name)
   608  // 		if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
   609  // 			if !tmName.isExported() {
   610  // 				tmPkgPath := tmName.pkgPath()
   611  // 				if tmPkgPath == "" {
   612  // 					tmPkgPath = t.pkgPath.name()
   613  // 				}
   614  // 				vmPkgPath := vmName.pkgPath()
   615  // 				if vmPkgPath == "" {
   616  // 					vmPkgPath = V.nameOff(v.pkgPath).name()
   617  // 				}
   618  // 				if tmPkgPath != vmPkgPath {
   619  // 					continue
   620  // 				}
   621  // 			}
   622  // 			if i++; i >= len(t.methods) {
   623  // 				return true
   624  // 			}
   625  // 		}
   626  // 	}
   627  // 	return false
   628  // }
   629  
   630  func (t *rtype) MethodX(i int) (m reflect.Method) {
   631  	if t.Kind() == reflect.Interface {
   632  		return toType(t).Method(i)
   633  	}
   634  	methods := t.methods()
   635  	if i < 0 || i >= len(methods) {
   636  		panic("reflect: Method index out of range")
   637  	}
   638  	p := methods[i]
   639  	pname := t.nameOff(p.name)
   640  	m.Name = pname.name()
   641  	m.Index = i
   642  	fl := flag(reflect.Func)
   643  	mtyp := t.typeOff(p.mtyp)
   644  	if mtyp == nil {
   645  		return
   646  	}
   647  	ft := (*funcType)(unsafe.Pointer(mtyp))
   648  	in := make([]reflect.Type, 0, 1+len(ft.in()))
   649  	in = append(in, toType(t))
   650  	for _, arg := range ft.in() {
   651  		in = append(in, toType(arg))
   652  	}
   653  	out := make([]reflect.Type, 0, len(ft.out()))
   654  	for _, ret := range ft.out() {
   655  		out = append(out, toType(ret))
   656  	}
   657  	mt := reflect.FuncOf(in, out, ft.IsVariadic())
   658  	m.Type = mt
   659  	tfn := t.textOff(p.tfn)
   660  	fn := unsafe.Pointer(&tfn)
   661  	m.Func = toValue(Value{totype(mt), fn, fl})
   662  	return m
   663  }
   664  
   665  func (t *rtype) MethodByNameX(name string) (m reflect.Method, ok bool) {
   666  	if t.Kind() == reflect.Interface {
   667  		return toType(t).MethodByName(name)
   668  	}
   669  	ut := t.uncommon()
   670  	if ut == nil {
   671  		return reflect.Method{}, false
   672  	}
   673  	for i, p := range ut.methods() {
   674  		if t.nameOff(p.name).name() == name {
   675  			return t.MethodX(i), true
   676  		}
   677  	}
   678  	return reflect.Method{}, false
   679  }
   680  
   681  func NumMethodX(typ reflect.Type) int {
   682  	return len(totype(typ).methods())
   683  }
   684  
   685  func MethodX(typ reflect.Type, i int) reflect.Method {
   686  	return totype(typ).MethodX(i)
   687  }
   688  
   689  func MethodByNameX(typ reflect.Type, name string) (m reflect.Method, ok bool) {
   690  	return totype(typ).MethodByNameX(name)
   691  }
   692  
   693  // Field returns the i'th field of the struct v.
   694  // It panics if v's Kind is not Struct or i is out of range.
   695  func FieldX(v reflect.Value, i int) reflect.Value {
   696  	mustBe("reflect.Value.Field", v, reflect.Struct)
   697  	rv := tovalue(&v)
   698  	tt := toStructType(rv.typ)
   699  	if uint(i) >= uint(len(tt.fields)) {
   700  		panic("reflect: Field index out of range")
   701  	}
   702  	field := &tt.fields[i]
   703  	typ := field.typ
   704  
   705  	// Inherit permission bits from v, but clear flagEmbedRO.
   706  	fl := rv.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
   707  	// Using an unexported field forces flagRO.
   708  	// if !field.name.isExported() {
   709  	// 	if field.embedded() {
   710  	// 		fl |= flagEmbedRO
   711  	// 	} else {
   712  	// 		fl |= flagStickyRO
   713  	// 	}
   714  	// }
   715  	// Either flagIndir is set and v.ptr points at struct,
   716  	// or flagIndir is not set and v.ptr is the actual struct data.
   717  	// In the former case, we want v.ptr + offset.
   718  	// In the latter case, we must have field.offset = 0,
   719  	// so v.ptr + field.offset is still the correct address.
   720  	ptr := add(rv.ptr, field.offset(), "same as non-reflect &v.field")
   721  	return toValue(Value{typ, ptr, fl})
   722  }