github.com/FISCO-BCOS/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/internal/reflectlite/type.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package reflectlite implements lightweight version of reflect, not using 6 // any package except for "runtime" 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 }