github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/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 // go/types.cc 114 // runtime/type.go 115 type tflag uint8 116 117 const ( 118 // tflagRegularMemory means that equal and hash functions can treat 119 // this type as a single region of t.size bytes. 120 tflagRegularMemory tflag = 1 << 3 121 ) 122 123 // rtype is the common implementation of most values. 124 // It is embedded in other struct types. 125 // 126 // rtype must be kept in sync with ../runtime/type.go:/^type._type. 127 type rtype struct { 128 size uintptr 129 ptrdata uintptr // number of bytes in the type that can contain pointers 130 hash uint32 // hash of type; avoids computation in hash tables 131 tflag tflag // extra type information flags 132 align uint8 // alignment of variable with this type 133 fieldAlign uint8 // alignment of struct field with this type 134 kind uint8 // enumeration for C 135 // function for comparing objects of this type 136 // (ptr to object A, ptr to object B) -> ==? 137 equal func(unsafe.Pointer, unsafe.Pointer) bool 138 gcdata *byte // garbage collection data 139 string *string // string form; unnecessary but undeniably useful 140 *uncommonType // (relatively) uncommon fields 141 ptrToThis *rtype // type for pointer to this type, may be zero 142 } 143 144 // Method on non-interface type 145 type method struct { 146 name *string // name of method 147 pkgPath *string // nil for exported Names; otherwise import path 148 mtyp *rtype // method type (without receiver) 149 typ *rtype // .(*FuncType) underneath (with receiver) 150 tfn unsafe.Pointer // fn used for normal method call 151 } 152 153 // uncommonType is present only for defined types or types with methods 154 // (if T is a defined type, the uncommonTypes for T and *T have methods). 155 // Using a pointer to this struct reduces the overall size required 156 // to describe a non-defined type with no methods. 157 type uncommonType struct { 158 name *string // name of type 159 pkgPath *string // import path; nil for built-in types like int, string 160 methods []method // methods associated with type 161 } 162 163 // chanDir represents a channel type's direction. 164 type chanDir int 165 166 const ( 167 recvDir chanDir = 1 << iota // <-chan 168 sendDir // chan<- 169 bothDir = recvDir | sendDir // chan 170 ) 171 172 // arrayType represents a fixed array type. 173 type arrayType struct { 174 rtype 175 elem *rtype // array element type 176 slice *rtype // slice type 177 len uintptr 178 } 179 180 // chanType represents a channel type. 181 type chanType struct { 182 rtype 183 elem *rtype // channel element type 184 dir uintptr // channel direction (chanDir) 185 } 186 187 // funcType represents a function type. 188 type funcType struct { 189 rtype 190 dotdotdot bool // last input parameter is ... 191 in []*rtype // input parameter types 192 out []*rtype // output parameter types 193 } 194 195 // imethod represents a method on an interface type 196 type imethod struct { 197 name *string // name of method 198 pkgPath *string // nil for exported Names; otherwise import path 199 typ *rtype // .(*FuncType) underneath 200 } 201 202 // interfaceType represents an interface type. 203 type interfaceType struct { 204 rtype 205 methods []imethod // sorted by hash 206 } 207 208 // mapType represents a map type. 209 type mapType struct { 210 rtype 211 key *rtype // map key type 212 elem *rtype // map element (value) type 213 bucket *rtype // internal bucket structure 214 keysize uint8 // size of key slot 215 valuesize uint8 // size of value slot 216 bucketsize uint16 // size of bucket 217 flags uint32 218 } 219 220 // ptrType represents a pointer type. 221 type ptrType struct { 222 rtype 223 elem *rtype // pointer element (pointed at) type 224 } 225 226 // sliceType represents a slice type. 227 type sliceType struct { 228 rtype 229 elem *rtype // slice element type 230 } 231 232 // Struct field 233 type structField struct { 234 name *string // name is always non-empty 235 pkgPath *string // nil for exported Names; otherwise import path 236 typ *rtype // type of field 237 tag *string // nil if no tag 238 offsetEmbed uintptr // byte offset of field<<1 | isAnonymous 239 } 240 241 func (f *structField) offset() uintptr { 242 return f.offsetEmbed >> 1 243 } 244 245 func (f *structField) embedded() bool { 246 return f.offsetEmbed&1 != 0 247 } 248 249 // structType represents a struct type. 250 type structType struct { 251 rtype 252 fields []structField // sorted by offset 253 } 254 255 /* 256 * The compiler knows the exact layout of all the data structures above. 257 * The compiler does not know about the data structures and methods below. 258 */ 259 260 const ( 261 kindDirectIface = 1 << 5 262 kindGCProg = 1 << 6 // Type.gc points to GC program 263 kindMask = (1 << 5) - 1 264 ) 265 266 func (t *uncommonType) exportedMethods() []method { 267 allm := t.methods 268 allExported := true 269 for _, m := range allm { 270 if m.pkgPath != nil { 271 allExported = false 272 break 273 } 274 } 275 var methods []method 276 if allExported { 277 methods = allm 278 } else { 279 methods = make([]method, 0, len(allm)) 280 for _, m := range allm { 281 if m.pkgPath == nil { 282 methods = append(methods, m) 283 } 284 } 285 methods = methods[:len(methods):len(methods)] 286 } 287 288 return methods 289 } 290 291 func (t *uncommonType) uncommon() *uncommonType { 292 return t 293 } 294 295 func (t *uncommonType) PkgPath() string { 296 if t == nil || t.pkgPath == nil { 297 return "" 298 } 299 return *t.pkgPath 300 } 301 302 func (t *uncommonType) Name() string { 303 if t == nil || t.name == nil { 304 return "" 305 } 306 return *t.name 307 } 308 309 func (t *rtype) String() string { 310 // For gccgo, strip out quoted strings. 311 s := *t.string 312 var q bool 313 r := make([]byte, len(s)) 314 j := 0 315 for i := 0; i < len(s); i++ { 316 if s[i] == '\t' { 317 q = !q 318 } else if !q { 319 r[j] = s[i] 320 j++ 321 } 322 } 323 return string(r[:j]) 324 } 325 326 func (t *rtype) Size() uintptr { return t.size } 327 328 func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) } 329 330 func (t *rtype) pointers() bool { return t.ptrdata != 0 } 331 332 func (t *rtype) common() *rtype { return t } 333 334 func (t *rtype) exportedMethods() []method { 335 ut := t.uncommon() 336 if ut == nil { 337 return nil 338 } 339 return ut.exportedMethods() 340 } 341 342 func (t *rtype) NumMethod() int { 343 if t.Kind() == Interface { 344 tt := (*interfaceType)(unsafe.Pointer(t)) 345 return tt.NumMethod() 346 } 347 return len(t.exportedMethods()) 348 } 349 350 func (t *rtype) PkgPath() string { 351 return t.uncommonType.PkgPath() 352 } 353 354 func (t *rtype) hasName() bool { 355 return t.uncommonType != nil && t.uncommonType.name != nil 356 } 357 358 func (t *rtype) Name() string { 359 return t.uncommonType.Name() 360 } 361 362 func (t *rtype) chanDir() chanDir { 363 if t.Kind() != Chan { 364 panic("reflect: chanDir of non-chan type") 365 } 366 tt := (*chanType)(unsafe.Pointer(t)) 367 return chanDir(tt.dir) 368 } 369 370 func (t *rtype) Elem() Type { 371 switch t.Kind() { 372 case Array: 373 tt := (*arrayType)(unsafe.Pointer(t)) 374 return toType(tt.elem) 375 case Chan: 376 tt := (*chanType)(unsafe.Pointer(t)) 377 return toType(tt.elem) 378 case Map: 379 tt := (*mapType)(unsafe.Pointer(t)) 380 return toType(tt.elem) 381 case Ptr: 382 tt := (*ptrType)(unsafe.Pointer(t)) 383 return toType(tt.elem) 384 case Slice: 385 tt := (*sliceType)(unsafe.Pointer(t)) 386 return toType(tt.elem) 387 } 388 panic("reflect: Elem of invalid type") 389 } 390 391 func (t *rtype) In(i int) Type { 392 if t.Kind() != Func { 393 panic("reflect: In of non-func type") 394 } 395 tt := (*funcType)(unsafe.Pointer(t)) 396 return toType(tt.in[i]) 397 } 398 399 func (t *rtype) Key() Type { 400 if t.Kind() != Map { 401 panic("reflect: Key of non-map type") 402 } 403 tt := (*mapType)(unsafe.Pointer(t)) 404 return toType(tt.key) 405 } 406 407 func (t *rtype) Len() int { 408 if t.Kind() != Array { 409 panic("reflect: Len of non-array type") 410 } 411 tt := (*arrayType)(unsafe.Pointer(t)) 412 return int(tt.len) 413 } 414 415 func (t *rtype) NumField() int { 416 if t.Kind() != Struct { 417 panic("reflect: NumField of non-struct type") 418 } 419 tt := (*structType)(unsafe.Pointer(t)) 420 return len(tt.fields) 421 } 422 423 func (t *rtype) NumIn() int { 424 if t.Kind() != Func { 425 panic("reflect: NumIn of non-func type") 426 } 427 tt := (*funcType)(unsafe.Pointer(t)) 428 return len(tt.in) 429 } 430 431 func (t *rtype) NumOut() int { 432 if t.Kind() != Func { 433 panic("reflect: NumOut of non-func type") 434 } 435 tt := (*funcType)(unsafe.Pointer(t)) 436 return len(tt.out) 437 } 438 439 func (t *rtype) Out(i int) Type { 440 if t.Kind() != Func { 441 panic("reflect: Out of non-func type") 442 } 443 tt := (*funcType)(unsafe.Pointer(t)) 444 return toType(tt.out[i]) 445 } 446 447 // add returns p+x. 448 // 449 // The whySafe string is ignored, so that the function still inlines 450 // as efficiently as p+x, but all call sites should use the string to 451 // record why the addition is safe, which is to say why the addition 452 // does not cause x to advance to the very end of p's allocation 453 // and therefore point incorrectly at the next block in memory. 454 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer { 455 return unsafe.Pointer(uintptr(p) + x) 456 } 457 458 // NumMethod returns the number of interface methods in the type's method set. 459 func (t *interfaceType) NumMethod() int { return len(t.methods) } 460 461 // TypeOf returns the reflection Type that represents the dynamic type of i. 462 // If i is a nil interface value, TypeOf returns nil. 463 func TypeOf(i interface{}) Type { 464 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 465 return toType(eface.typ) 466 } 467 468 func (t *rtype) Implements(u Type) bool { 469 if u == nil { 470 panic("reflect: nil type passed to Type.Implements") 471 } 472 if u.Kind() != Interface { 473 panic("reflect: non-interface type passed to Type.Implements") 474 } 475 return implements(u.(*rtype), t) 476 } 477 478 func (t *rtype) AssignableTo(u Type) bool { 479 if u == nil { 480 panic("reflect: nil type passed to Type.AssignableTo") 481 } 482 uu := u.(*rtype) 483 return directlyAssignable(uu, t) || implements(uu, t) 484 } 485 486 func (t *rtype) Comparable() bool { 487 switch t.Kind() { 488 case Bool, Int, Int8, Int16, Int32, Int64, 489 Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, 490 Float32, Float64, Complex64, Complex128, 491 Chan, Interface, Ptr, String, UnsafePointer: 492 return true 493 494 case Func, Map, Slice: 495 return false 496 497 case Array: 498 return (*arrayType)(unsafe.Pointer(t)).elem.Comparable() 499 500 case Struct: 501 tt := (*structType)(unsafe.Pointer(t)) 502 for i := range tt.fields { 503 if !tt.fields[i].typ.Comparable() { 504 return false 505 } 506 } 507 return true 508 509 default: 510 panic("reflectlite: impossible") 511 } 512 } 513 514 // implements reports whether the type V implements the interface type T. 515 func implements(T, V *rtype) bool { 516 if T.Kind() != Interface { 517 return false 518 } 519 t := (*interfaceType)(unsafe.Pointer(T)) 520 if len(t.methods) == 0 { 521 return true 522 } 523 524 // The same algorithm applies in both cases, but the 525 // method tables for an interface type and a concrete type 526 // are different, so the code is duplicated. 527 // In both cases the algorithm is a linear scan over the two 528 // lists - T's methods and V's methods - simultaneously. 529 // Since method tables are stored in a unique sorted order 530 // (alphabetical, with no duplicate method names), the scan 531 // through V's methods must hit a match for each of T's 532 // methods along the way, or else V does not implement T. 533 // This lets us run the scan in overall linear time instead of 534 // the quadratic time a naive search would require. 535 // See also ../runtime/iface.go. 536 if V.Kind() == Interface { 537 v := (*interfaceType)(unsafe.Pointer(V)) 538 i := 0 539 for j := 0; j < len(v.methods); j++ { 540 tm := &t.methods[i] 541 vm := &v.methods[j] 542 if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.typ).common() == toType(tm.typ).common() { 543 if i++; i >= len(t.methods) { 544 return true 545 } 546 } 547 } 548 return false 549 } 550 551 v := V.uncommon() 552 if v == nil { 553 return false 554 } 555 i := 0 556 for j := 0; j < len(v.methods); j++ { 557 tm := &t.methods[i] 558 vm := &v.methods[j] 559 if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.mtyp).common() == toType(tm.typ).common() { 560 if i++; i >= len(t.methods) { 561 return true 562 } 563 } 564 } 565 return false 566 } 567 568 // directlyAssignable reports whether a value x of type V can be directly 569 // assigned (using memmove) to a value of type T. 570 // https://golang.org/doc/go_spec.html#Assignability 571 // Ignoring the interface rules (implemented elsewhere) 572 // and the ideal constant rules (no ideal constants at run time). 573 func directlyAssignable(T, V *rtype) bool { 574 // x's type V is identical to T? 575 if T == V { 576 return true 577 } 578 579 // Otherwise at least one of T and V must not be defined 580 // and they must have the same kind. 581 if T.hasName() && V.hasName() || T.Kind() != V.Kind() { 582 return false 583 } 584 585 // x's type T and V must have identical underlying types. 586 return haveIdenticalUnderlyingType(T, V, true) 587 } 588 589 func haveIdenticalType(T, V Type, cmpTags bool) bool { 590 if cmpTags { 591 return T == V 592 } 593 594 if T.Name() != V.Name() || T.Kind() != V.Kind() { 595 return false 596 } 597 598 return haveIdenticalUnderlyingType(T.common(), V.common(), false) 599 } 600 601 func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool { 602 if T == V { 603 return true 604 } 605 606 kind := T.Kind() 607 if kind != V.Kind() { 608 return false 609 } 610 611 // Non-composite types of equal kind have same underlying type 612 // (the predefined instance of the type). 613 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer { 614 return true 615 } 616 617 // Composite types. 618 switch kind { 619 case Array: 620 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 621 622 case Chan: 623 // Special case: 624 // x is a bidirectional channel value, T is a channel type, 625 // and x's type V and T have identical element types. 626 if V.chanDir() == bothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) { 627 return true 628 } 629 630 // Otherwise continue test for identical underlying type. 631 return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 632 633 case Func: 634 t := (*funcType)(unsafe.Pointer(T)) 635 v := (*funcType)(unsafe.Pointer(V)) 636 if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) { 637 return false 638 } 639 for i, typ := range t.in { 640 if !haveIdenticalType(typ, v.in[i], cmpTags) { 641 return false 642 } 643 } 644 for i, typ := range t.out { 645 if !haveIdenticalType(typ, v.out[i], cmpTags) { 646 return false 647 } 648 } 649 return true 650 651 case Interface: 652 t := (*interfaceType)(unsafe.Pointer(T)) 653 v := (*interfaceType)(unsafe.Pointer(V)) 654 if len(t.methods) == 0 && len(v.methods) == 0 { 655 return true 656 } 657 // Might have the same methods but still 658 // need a run time conversion. 659 return false 660 661 case Map: 662 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 663 664 case Ptr, Slice: 665 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 666 667 case Struct: 668 t := (*structType)(unsafe.Pointer(T)) 669 v := (*structType)(unsafe.Pointer(V)) 670 if len(t.fields) != len(v.fields) { 671 return false 672 } 673 for i := range t.fields { 674 tf := &t.fields[i] 675 vf := &v.fields[i] 676 if tf.name != vf.name && (tf.name == nil || vf.name == nil || *tf.name != *vf.name) { 677 return false 678 } 679 if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) { 680 return false 681 } 682 if !haveIdenticalType(tf.typ, vf.typ, cmpTags) { 683 return false 684 } 685 if cmpTags && tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) { 686 return false 687 } 688 if tf.offsetEmbed != vf.offsetEmbed { 689 return false 690 } 691 } 692 return true 693 } 694 695 return false 696 } 697 698 // toType converts from a *rtype to a Type that can be returned 699 // to the client of package reflect. In gc, the only concern is that 700 // a nil *rtype must be replaced by a nil Type, but in gccgo this 701 // function takes care of ensuring that multiple *rtype for the same 702 // type are coalesced into a single Type. 703 func toType(t *rtype) Type { 704 if t == nil { 705 return nil 706 } 707 return t 708 } 709 710 // ifaceIndir reports whether t is stored indirectly in an interface value. 711 func ifaceIndir(t *rtype) bool { 712 return t.kind&kindDirectIface == 0 713 }