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 }