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