github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/reflect/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 reflect implements run-time reflection, allowing a program to 6 // manipulate objects with arbitrary types. The typical use is to take a value 7 // with static type interface{} and extract its dynamic type information by 8 // calling TypeOf, which returns a Type. 9 // 10 // A call to ValueOf returns a Value representing the run-time data. 11 // Zero takes a Type and returns a Value representing a zero value 12 // for that type. 13 // 14 // See "The Laws of Reflection" for an introduction to reflection in Go: 15 // https://golang.org/doc/articles/laws_of_reflection.html 16 package reflect 17 18 import ( 19 "runtime" 20 "strconv" 21 "sync" 22 "unsafe" 23 ) 24 25 // Type is the representation of a Go type. 26 // 27 // Not all methods apply to all kinds of types. Restrictions, 28 // if any, are noted in the documentation for each method. 29 // Use the Kind method to find out the kind of type before 30 // calling kind-specific methods. Calling a method 31 // inappropriate to the kind of type causes a run-time panic. 32 type Type interface { 33 // Methods applicable to all types. 34 35 // Align returns the alignment in bytes of a value of 36 // this type when allocated in memory. 37 Align() int 38 39 // FieldAlign returns the alignment in bytes of a value of 40 // this type when used as a field in a struct. 41 FieldAlign() int 42 43 // Method returns the i'th method in the type's method set. 44 // It panics if i is not in the range [0, NumMethod()). 45 // 46 // For a non-interface type T or *T, the returned Method's Type and Func 47 // fields describe a function whose first argument is the receiver. 48 // 49 // For an interface type, the returned Method's Type field gives the 50 // method signature, without a receiver, and the Func field is nil. 51 Method(int) Method 52 53 // MethodByName returns the method with that name in the type's 54 // method set and a boolean indicating if the method was found. 55 // 56 // For a non-interface type T or *T, the returned Method's Type and Func 57 // fields describe a function whose first argument is the receiver. 58 // 59 // For an interface type, the returned Method's Type field gives the 60 // method signature, without a receiver, and the Func field is nil. 61 MethodByName(string) (Method, bool) 62 63 // NumMethod returns the number of methods in the type's method set. 64 NumMethod() int 65 66 // Name returns the type's name within its package. 67 // It returns an empty string for unnamed types. 68 Name() string 69 70 // PkgPath returns a named type's package path, that is, the import path 71 // that uniquely identifies the package, such as "encoding/base64". 72 // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int), 73 // the package path will be the empty string. 74 PkgPath() string 75 76 // Size returns the number of bytes needed to store 77 // a value of the given type; it is analogous to unsafe.Sizeof. 78 Size() uintptr 79 80 // String returns a string representation of the type. 81 // The string representation may use shortened package names 82 // (e.g., base64 instead of "encoding/base64") and is not 83 // guaranteed to be unique among types. To test for equality, 84 // compare the Types directly. 85 String() string 86 87 // Used internally by gccgo--the string retaining quoting. 88 rawString() string 89 90 // Kind returns the specific kind of this type. 91 Kind() Kind 92 93 // Implements reports whether the type implements the interface type u. 94 Implements(u Type) bool 95 96 // AssignableTo reports whether a value of the type is assignable to type u. 97 AssignableTo(u Type) bool 98 99 // ConvertibleTo reports whether a value of the type is convertible to type u. 100 ConvertibleTo(u Type) bool 101 102 // Comparable reports whether values of this type are comparable. 103 Comparable() bool 104 105 // Methods applicable only to some types, depending on Kind. 106 // The methods allowed for each kind are: 107 // 108 // Int*, Uint*, Float*, Complex*: Bits 109 // Array: Elem, Len 110 // Chan: ChanDir, Elem 111 // Func: In, NumIn, Out, NumOut, IsVariadic. 112 // Map: Key, Elem 113 // Ptr: Elem 114 // Slice: Elem 115 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField 116 117 // Bits returns the size of the type in bits. 118 // It panics if the type's Kind is not one of the 119 // sized or unsized Int, Uint, Float, or Complex kinds. 120 Bits() int 121 122 // ChanDir returns a channel type's direction. 123 // It panics if the type's Kind is not Chan. 124 ChanDir() ChanDir 125 126 // IsVariadic reports whether a function type's final input parameter 127 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's 128 // implicit actual type []T. 129 // 130 // For concreteness, if t represents func(x int, y ... float64), then 131 // 132 // t.NumIn() == 2 133 // t.In(0) is the reflect.Type for "int" 134 // t.In(1) is the reflect.Type for "[]float64" 135 // t.IsVariadic() == true 136 // 137 // IsVariadic panics if the type's Kind is not Func. 138 IsVariadic() bool 139 140 // Elem returns a type's element type. 141 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. 142 Elem() Type 143 144 // Field returns a struct type's i'th field. 145 // It panics if the type's Kind is not Struct. 146 // It panics if i is not in the range [0, NumField()). 147 Field(i int) StructField 148 149 // FieldByIndex returns the nested field corresponding 150 // to the index sequence. It is equivalent to calling Field 151 // successively for each index i. 152 // It panics if the type's Kind is not Struct. 153 FieldByIndex(index []int) StructField 154 155 // FieldByName returns the struct field with the given name 156 // and a boolean indicating if the field was found. 157 FieldByName(name string) (StructField, bool) 158 159 // FieldByNameFunc returns the first struct field with a name 160 // that satisfies the match function and a boolean indicating if 161 // the field was found. 162 FieldByNameFunc(match func(string) bool) (StructField, bool) 163 164 // In returns the type of a function type's i'th input parameter. 165 // It panics if the type's Kind is not Func. 166 // It panics if i is not in the range [0, NumIn()). 167 In(i int) Type 168 169 // Key returns a map type's key type. 170 // It panics if the type's Kind is not Map. 171 Key() Type 172 173 // Len returns an array type's length. 174 // It panics if the type's Kind is not Array. 175 Len() int 176 177 // NumField returns a struct type's field count. 178 // It panics if the type's Kind is not Struct. 179 NumField() int 180 181 // NumIn returns a function type's input parameter count. 182 // It panics if the type's Kind is not Func. 183 NumIn() int 184 185 // NumOut returns a function type's output parameter count. 186 // It panics if the type's Kind is not Func. 187 NumOut() int 188 189 // Out returns the type of a function type's i'th output parameter. 190 // It panics if the type's Kind is not Func. 191 // It panics if i is not in the range [0, NumOut()). 192 Out(i int) Type 193 194 common() *rtype 195 uncommon() *uncommonType 196 } 197 198 // BUG(rsc): FieldByName and related functions consider struct field names to be equal 199 // if the names are equal, even if they are unexported names originating 200 // in different packages. The practical effect of this is that the result of 201 // t.FieldByName("x") is not well defined if the struct type t contains 202 // multiple fields named x (embedded from different packages). 203 // FieldByName may return one of the fields named x or may report that there are none. 204 // See golang.org/issue/4876 for more details. 205 206 /* 207 * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go). 208 * A few are known to ../runtime/type.go to convey to debuggers. 209 * They are also known to ../runtime/type.go. 210 */ 211 212 // A Kind represents the specific kind of type that a Type represents. 213 // The zero Kind is not a valid kind. 214 type Kind uint 215 216 const ( 217 Invalid Kind = iota 218 Bool 219 Int 220 Int8 221 Int16 222 Int32 223 Int64 224 Uint 225 Uint8 226 Uint16 227 Uint32 228 Uint64 229 Uintptr 230 Float32 231 Float64 232 Complex64 233 Complex128 234 Array 235 Chan 236 Func 237 Interface 238 Map 239 Ptr 240 Slice 241 String 242 Struct 243 UnsafePointer 244 ) 245 246 // rtype is the common implementation of most values. 247 // It is embedded in other, public struct types, but always 248 // with a unique tag like `reflect:"array"` or `reflect:"ptr"` 249 // so that code cannot convert from, say, *arrayType to *ptrType. 250 type rtype struct { 251 kind uint8 // enumeration for C 252 align int8 // alignment of variable with this type 253 fieldAlign uint8 // alignment of struct field with this type 254 _ uint8 // unused/padding 255 size uintptr 256 hash uint32 // hash of type; avoids computation in hash tables 257 258 hashfn func(unsafe.Pointer, uintptr) uintptr // hash function 259 equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool // equality function 260 261 gc unsafe.Pointer // garbage collection data 262 string *string // string form; unnecessary but undeniably useful 263 *uncommonType // (relatively) uncommon fields 264 ptrToThis *rtype // type for pointer to this type, if used in binary or has methods 265 } 266 267 // Method on non-interface type 268 type method struct { 269 name *string // name of method 270 pkgPath *string // nil for exported Names; otherwise import path 271 mtyp *rtype // method type (without receiver) 272 typ *rtype // .(*FuncType) underneath (with receiver) 273 tfn unsafe.Pointer // fn used for normal method call 274 } 275 276 // uncommonType is present only for types with names or methods 277 // (if T is a named type, the uncommonTypes for T and *T have methods). 278 // Using a pointer to this struct reduces the overall size required 279 // to describe an unnamed type with no methods. 280 type uncommonType struct { 281 name *string // name of type 282 pkgPath *string // import path; nil for built-in types like int, string 283 methods []method // methods associated with type 284 } 285 286 // ChanDir represents a channel type's direction. 287 type ChanDir int 288 289 const ( 290 RecvDir ChanDir = 1 << iota // <-chan 291 SendDir // chan<- 292 BothDir = RecvDir | SendDir // chan 293 ) 294 295 // arrayType represents a fixed array type. 296 type arrayType struct { 297 rtype `reflect:"array"` 298 elem *rtype // array element type 299 slice *rtype // slice type 300 len uintptr 301 } 302 303 // chanType represents a channel type. 304 type chanType struct { 305 rtype `reflect:"chan"` 306 elem *rtype // channel element type 307 dir uintptr // channel direction (ChanDir) 308 } 309 310 // funcType represents a function type. 311 type funcType struct { 312 rtype `reflect:"func"` 313 dotdotdot bool // last input parameter is ... 314 in []*rtype // input parameter types 315 out []*rtype // output parameter types 316 } 317 318 // imethod represents a method on an interface type 319 type imethod struct { 320 name *string // name of method 321 pkgPath *string // nil for exported Names; otherwise import path 322 typ *rtype // .(*FuncType) underneath 323 } 324 325 // interfaceType represents an interface type. 326 type interfaceType struct { 327 rtype `reflect:"interface"` 328 methods []imethod // sorted by hash 329 } 330 331 // mapType represents a map type. 332 type mapType struct { 333 rtype `reflect:"map"` 334 key *rtype // map key type 335 elem *rtype // map element (value) type 336 } 337 338 // ptrType represents a pointer type. 339 type ptrType struct { 340 rtype `reflect:"ptr"` 341 elem *rtype // pointer element (pointed at) type 342 } 343 344 // sliceType represents a slice type. 345 type sliceType struct { 346 rtype `reflect:"slice"` 347 elem *rtype // slice element type 348 } 349 350 // Struct field 351 type structField struct { 352 name *string // nil for embedded fields 353 pkgPath *string // nil for exported Names; otherwise import path 354 typ *rtype // type of field 355 tag *string // nil if no tag 356 offset uintptr // byte offset of field within struct 357 } 358 359 // structType represents a struct type. 360 type structType struct { 361 rtype `reflect:"struct"` 362 fields []structField // sorted by offset 363 } 364 365 // NOTE: These are copied from ../runtime/mgc0.h. 366 // They must be kept in sync. 367 const ( 368 _GC_END = iota 369 _GC_PTR 370 _GC_APTR 371 _GC_ARRAY_START 372 _GC_ARRAY_NEXT 373 _GC_CALL 374 _GC_CHAN_PTR 375 _GC_STRING 376 _GC_EFACE 377 _GC_IFACE 378 _GC_SLICE 379 _GC_REGION 380 _GC_NUM_INSTR 381 ) 382 383 /* 384 * The compiler knows the exact layout of all the data structures above. 385 * The compiler does not know about the data structures and methods below. 386 */ 387 388 // Method represents a single method. 389 type Method struct { 390 // Name is the method name. 391 // PkgPath is the package path that qualifies a lower case (unexported) 392 // method name. It is empty for upper case (exported) method names. 393 // The combination of PkgPath and Name uniquely identifies a method 394 // in a method set. 395 // See https://golang.org/ref/spec#Uniqueness_of_identifiers 396 Name string 397 PkgPath string 398 399 Type Type // method type 400 Func Value // func with receiver as first argument 401 Index int // index for Type.Method 402 } 403 404 const ( 405 kindDirectIface = 1 << 5 406 kindGCProg = 1 << 6 // Type.gc points to GC program 407 kindNoPointers = 1 << 7 408 kindMask = (1 << 5) - 1 409 ) 410 411 func (k Kind) String() string { 412 if int(k) < len(kindNames) { 413 return kindNames[k] 414 } 415 return "kind" + strconv.Itoa(int(k)) 416 } 417 418 var kindNames = []string{ 419 Invalid: "invalid", 420 Bool: "bool", 421 Int: "int", 422 Int8: "int8", 423 Int16: "int16", 424 Int32: "int32", 425 Int64: "int64", 426 Uint: "uint", 427 Uint8: "uint8", 428 Uint16: "uint16", 429 Uint32: "uint32", 430 Uint64: "uint64", 431 Uintptr: "uintptr", 432 Float32: "float32", 433 Float64: "float64", 434 Complex64: "complex64", 435 Complex128: "complex128", 436 Array: "array", 437 Chan: "chan", 438 Func: "func", 439 Interface: "interface", 440 Map: "map", 441 Ptr: "ptr", 442 Slice: "slice", 443 String: "string", 444 Struct: "struct", 445 UnsafePointer: "unsafe.Pointer", 446 } 447 448 func (t *uncommonType) uncommon() *uncommonType { 449 return t 450 } 451 452 func (t *uncommonType) PkgPath() string { 453 if t == nil || t.pkgPath == nil { 454 return "" 455 } 456 return *t.pkgPath 457 } 458 459 func (t *uncommonType) Name() string { 460 if t == nil || t.name == nil { 461 return "" 462 } 463 return *t.name 464 } 465 466 func (t *rtype) rawString() string { return *t.string } 467 468 func (t *rtype) String() string { 469 // For gccgo, strip out quoted strings. 470 s := *t.string 471 var q bool 472 r := make([]byte, len(s)) 473 j := 0 474 for i := 0; i < len(s); i++ { 475 if s[i] == '\t' { 476 q = !q 477 } else if !q { 478 r[j] = s[i] 479 j++ 480 } 481 } 482 return string(r[:j]) 483 } 484 485 func (t *rtype) Size() uintptr { return t.size } 486 487 func (t *rtype) Bits() int { 488 if t == nil { 489 panic("reflect: Bits of nil Type") 490 } 491 k := t.Kind() 492 if k < Int || k > Complex128 { 493 panic("reflect: Bits of non-arithmetic Type " + t.String()) 494 } 495 return int(t.size) * 8 496 } 497 498 func (t *rtype) Align() int { return int(t.align) } 499 500 func (t *rtype) FieldAlign() int { return int(t.fieldAlign) } 501 502 func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) } 503 504 func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 } 505 506 func (t *rtype) common() *rtype { return t } 507 508 func (t *uncommonType) Method(i int) (m Method) { 509 if t == nil || i < 0 || i >= len(t.methods) { 510 panic("reflect: Method index out of range") 511 } 512 p := &t.methods[i] 513 if p.name != nil { 514 m.Name = *p.name 515 } 516 fl := flag(Func) 517 if p.pkgPath != nil { 518 m.PkgPath = *p.pkgPath 519 fl |= flagStickyRO 520 } 521 mt := p.typ 522 m.Type = toType(mt) 523 x := new(unsafe.Pointer) 524 *x = unsafe.Pointer(&p.tfn) 525 m.Func = Value{mt, unsafe.Pointer(x), fl | flagIndir | flagMethodFn} 526 m.Index = i 527 return 528 } 529 530 func (t *uncommonType) NumMethod() int { 531 if t == nil { 532 return 0 533 } 534 return len(t.methods) 535 } 536 537 func (t *uncommonType) MethodByName(name string) (m Method, ok bool) { 538 if t == nil { 539 return 540 } 541 var p *method 542 for i := range t.methods { 543 p = &t.methods[i] 544 if p.name != nil && *p.name == name { 545 return t.Method(i), true 546 } 547 } 548 return 549 } 550 551 // TODO(rsc): gc supplies these, but they are not 552 // as efficient as they could be: they have commonType 553 // as the receiver instead of *rtype. 554 func (t *rtype) NumMethod() int { 555 if t.Kind() == Interface { 556 tt := (*interfaceType)(unsafe.Pointer(t)) 557 return tt.NumMethod() 558 } 559 return t.uncommonType.NumMethod() 560 } 561 562 func (t *rtype) Method(i int) (m Method) { 563 if t.Kind() == Interface { 564 tt := (*interfaceType)(unsafe.Pointer(t)) 565 return tt.Method(i) 566 } 567 return t.uncommonType.Method(i) 568 } 569 570 func (t *rtype) MethodByName(name string) (m Method, ok bool) { 571 if t.Kind() == Interface { 572 tt := (*interfaceType)(unsafe.Pointer(t)) 573 return tt.MethodByName(name) 574 } 575 return t.uncommonType.MethodByName(name) 576 } 577 578 func (t *rtype) PkgPath() string { 579 return t.uncommonType.PkgPath() 580 } 581 582 func (t *rtype) Name() string { 583 return t.uncommonType.Name() 584 } 585 586 func (t *rtype) ChanDir() ChanDir { 587 if t.Kind() != Chan { 588 panic("reflect: ChanDir of non-chan type") 589 } 590 tt := (*chanType)(unsafe.Pointer(t)) 591 return ChanDir(tt.dir) 592 } 593 594 func (t *rtype) IsVariadic() bool { 595 if t.Kind() != Func { 596 panic("reflect: IsVariadic of non-func type") 597 } 598 tt := (*funcType)(unsafe.Pointer(t)) 599 return tt.dotdotdot 600 } 601 602 func (t *rtype) Elem() Type { 603 switch t.Kind() { 604 case Array: 605 tt := (*arrayType)(unsafe.Pointer(t)) 606 return toType(tt.elem) 607 case Chan: 608 tt := (*chanType)(unsafe.Pointer(t)) 609 return toType(tt.elem) 610 case Map: 611 tt := (*mapType)(unsafe.Pointer(t)) 612 return toType(tt.elem) 613 case Ptr: 614 tt := (*ptrType)(unsafe.Pointer(t)) 615 return toType(tt.elem) 616 case Slice: 617 tt := (*sliceType)(unsafe.Pointer(t)) 618 return toType(tt.elem) 619 } 620 panic("reflect: Elem of invalid type") 621 } 622 623 func (t *rtype) Field(i int) StructField { 624 if t.Kind() != Struct { 625 panic("reflect: Field of non-struct type") 626 } 627 tt := (*structType)(unsafe.Pointer(t)) 628 return tt.Field(i) 629 } 630 631 func (t *rtype) FieldByIndex(index []int) StructField { 632 if t.Kind() != Struct { 633 panic("reflect: FieldByIndex of non-struct type") 634 } 635 tt := (*structType)(unsafe.Pointer(t)) 636 return tt.FieldByIndex(index) 637 } 638 639 func (t *rtype) FieldByName(name string) (StructField, bool) { 640 if t.Kind() != Struct { 641 panic("reflect: FieldByName of non-struct type") 642 } 643 tt := (*structType)(unsafe.Pointer(t)) 644 return tt.FieldByName(name) 645 } 646 647 func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) { 648 if t.Kind() != Struct { 649 panic("reflect: FieldByNameFunc of non-struct type") 650 } 651 tt := (*structType)(unsafe.Pointer(t)) 652 return tt.FieldByNameFunc(match) 653 } 654 655 func (t *rtype) In(i int) Type { 656 if t.Kind() != Func { 657 panic("reflect: In of non-func type") 658 } 659 tt := (*funcType)(unsafe.Pointer(t)) 660 return toType(tt.in[i]) 661 } 662 663 func (t *rtype) Key() Type { 664 if t.Kind() != Map { 665 panic("reflect: Key of non-map type") 666 } 667 tt := (*mapType)(unsafe.Pointer(t)) 668 return toType(tt.key) 669 } 670 671 func (t *rtype) Len() int { 672 if t.Kind() != Array { 673 panic("reflect: Len of non-array type") 674 } 675 tt := (*arrayType)(unsafe.Pointer(t)) 676 return int(tt.len) 677 } 678 679 func (t *rtype) NumField() int { 680 if t.Kind() != Struct { 681 panic("reflect: NumField of non-struct type") 682 } 683 tt := (*structType)(unsafe.Pointer(t)) 684 return len(tt.fields) 685 } 686 687 func (t *rtype) NumIn() int { 688 if t.Kind() != Func { 689 panic("reflect: NumIn of non-func type") 690 } 691 tt := (*funcType)(unsafe.Pointer(t)) 692 return len(tt.in) 693 } 694 695 func (t *rtype) NumOut() int { 696 if t.Kind() != Func { 697 panic("reflect: NumOut of non-func type") 698 } 699 tt := (*funcType)(unsafe.Pointer(t)) 700 return len(tt.out) 701 } 702 703 func (t *rtype) Out(i int) Type { 704 if t.Kind() != Func { 705 panic("reflect: Out of non-func type") 706 } 707 tt := (*funcType)(unsafe.Pointer(t)) 708 return toType(tt.out[i]) 709 } 710 711 func (d ChanDir) String() string { 712 switch d { 713 case SendDir: 714 return "chan<-" 715 case RecvDir: 716 return "<-chan" 717 case BothDir: 718 return "chan" 719 } 720 return "ChanDir" + strconv.Itoa(int(d)) 721 } 722 723 // Method returns the i'th method in the type's method set. 724 func (t *interfaceType) Method(i int) (m Method) { 725 if i < 0 || i >= len(t.methods) { 726 return 727 } 728 p := &t.methods[i] 729 m.Name = *p.name 730 if p.pkgPath != nil { 731 m.PkgPath = *p.pkgPath 732 } 733 m.Type = toType(p.typ) 734 m.Index = i 735 return 736 } 737 738 // NumMethod returns the number of interface methods in the type's method set. 739 func (t *interfaceType) NumMethod() int { return len(t.methods) } 740 741 // MethodByName method with the given name in the type's method set. 742 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) { 743 if t == nil { 744 return 745 } 746 var p *imethod 747 for i := range t.methods { 748 p = &t.methods[i] 749 if *p.name == name { 750 return t.Method(i), true 751 } 752 } 753 return 754 } 755 756 // A StructField describes a single field in a struct. 757 type StructField struct { 758 // Name is the field name. 759 // PkgPath is the package path that qualifies a lower case (unexported) 760 // field name. It is empty for upper case (exported) field names. 761 // See https://golang.org/ref/spec#Uniqueness_of_identifiers 762 Name string 763 PkgPath string 764 765 Type Type // field type 766 Tag StructTag // field tag string 767 Offset uintptr // offset within struct, in bytes 768 Index []int // index sequence for Type.FieldByIndex 769 Anonymous bool // is an embedded field 770 } 771 772 // A StructTag is the tag string in a struct field. 773 // 774 // By convention, tag strings are a concatenation of 775 // optionally space-separated key:"value" pairs. 776 // Each key is a non-empty string consisting of non-control 777 // characters other than space (U+0020 ' '), quote (U+0022 '"'), 778 // and colon (U+003A ':'). Each value is quoted using U+0022 '"' 779 // characters and Go string literal syntax. 780 type StructTag string 781 782 // Get returns the value associated with key in the tag string. 783 // If there is no such key in the tag, Get returns the empty string. 784 // If the tag does not have the conventional format, the value 785 // returned by Get is unspecified. 786 func (tag StructTag) Get(key string) string { 787 // When modifying this code, also update the validateStructTag code 788 // in golang.org/x/tools/cmd/vet/structtag.go. 789 790 for tag != "" { 791 // Skip leading space. 792 i := 0 793 for i < len(tag) && tag[i] == ' ' { 794 i++ 795 } 796 tag = tag[i:] 797 if tag == "" { 798 break 799 } 800 801 // Scan to colon. A space, a quote or a control character is a syntax error. 802 // Strictly speaking, control chars include the range [0x7f, 0x9f], not just 803 // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters 804 // as it is simpler to inspect the tag's bytes than the tag's runes. 805 i = 0 806 for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f { 807 i++ 808 } 809 if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' { 810 break 811 } 812 name := string(tag[:i]) 813 tag = tag[i+1:] 814 815 // Scan quoted string to find value. 816 i = 1 817 for i < len(tag) && tag[i] != '"' { 818 if tag[i] == '\\' { 819 i++ 820 } 821 i++ 822 } 823 if i >= len(tag) { 824 break 825 } 826 qvalue := string(tag[:i+1]) 827 tag = tag[i+1:] 828 829 if key == name { 830 value, err := strconv.Unquote(qvalue) 831 if err != nil { 832 break 833 } 834 return value 835 } 836 } 837 return "" 838 } 839 840 // Field returns the i'th struct field. 841 func (t *structType) Field(i int) (f StructField) { 842 if i < 0 || i >= len(t.fields) { 843 return 844 } 845 p := &t.fields[i] 846 f.Type = toType(p.typ) 847 if p.name != nil { 848 f.Name = *p.name 849 } else { 850 t := f.Type 851 if t.Kind() == Ptr { 852 t = t.Elem() 853 } 854 f.Name = t.Name() 855 f.Anonymous = true 856 } 857 if p.pkgPath != nil { 858 f.PkgPath = *p.pkgPath 859 } 860 if p.tag != nil { 861 f.Tag = StructTag(*p.tag) 862 } 863 f.Offset = p.offset 864 865 // NOTE(rsc): This is the only allocation in the interface 866 // presented by a reflect.Type. It would be nice to avoid, 867 // at least in the common cases, but we need to make sure 868 // that misbehaving clients of reflect cannot affect other 869 // uses of reflect. One possibility is CL 5371098, but we 870 // postponed that ugliness until there is a demonstrated 871 // need for the performance. This is issue 2320. 872 f.Index = []int{i} 873 return 874 } 875 876 // TODO(gri): Should there be an error/bool indicator if the index 877 // is wrong for FieldByIndex? 878 879 // FieldByIndex returns the nested field corresponding to index. 880 func (t *structType) FieldByIndex(index []int) (f StructField) { 881 f.Type = toType(&t.rtype) 882 for i, x := range index { 883 if i > 0 { 884 ft := f.Type 885 if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { 886 ft = ft.Elem() 887 } 888 f.Type = ft 889 } 890 f = f.Type.Field(x) 891 } 892 return 893 } 894 895 // A fieldScan represents an item on the fieldByNameFunc scan work list. 896 type fieldScan struct { 897 typ *structType 898 index []int 899 } 900 901 // FieldByNameFunc returns the struct field with a name that satisfies the 902 // match function and a boolean to indicate if the field was found. 903 func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) { 904 // This uses the same condition that the Go language does: there must be a unique instance 905 // of the match at a given depth level. If there are multiple instances of a match at the 906 // same depth, they annihilate each other and inhibit any possible match at a lower level. 907 // The algorithm is breadth first search, one depth level at a time. 908 909 // The current and next slices are work queues: 910 // current lists the fields to visit on this depth level, 911 // and next lists the fields on the next lower level. 912 current := []fieldScan{} 913 next := []fieldScan{{typ: t}} 914 915 // nextCount records the number of times an embedded type has been 916 // encountered and considered for queueing in the 'next' slice. 917 // We only queue the first one, but we increment the count on each. 918 // If a struct type T can be reached more than once at a given depth level, 919 // then it annihilates itself and need not be considered at all when we 920 // process that next depth level. 921 var nextCount map[*structType]int 922 923 // visited records the structs that have been considered already. 924 // Embedded pointer fields can create cycles in the graph of 925 // reachable embedded types; visited avoids following those cycles. 926 // It also avoids duplicated effort: if we didn't find the field in an 927 // embedded type T at level 2, we won't find it in one at level 4 either. 928 visited := map[*structType]bool{} 929 930 for len(next) > 0 { 931 current, next = next, current[:0] 932 count := nextCount 933 nextCount = nil 934 935 // Process all the fields at this depth, now listed in 'current'. 936 // The loop queues embedded fields found in 'next', for processing during the next 937 // iteration. The multiplicity of the 'current' field counts is recorded 938 // in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'. 939 for _, scan := range current { 940 t := scan.typ 941 if visited[t] { 942 // We've looked through this type before, at a higher level. 943 // That higher level would shadow the lower level we're now at, 944 // so this one can't be useful to us. Ignore it. 945 continue 946 } 947 visited[t] = true 948 for i := range t.fields { 949 f := &t.fields[i] 950 // Find name and type for field f. 951 var fname string 952 var ntyp *rtype 953 if f.name != nil { 954 fname = *f.name 955 } else { 956 // Anonymous field of type T or *T. 957 // Name taken from type. 958 ntyp = f.typ 959 if ntyp.Kind() == Ptr { 960 ntyp = ntyp.Elem().common() 961 } 962 fname = ntyp.Name() 963 } 964 965 // Does it match? 966 if match(fname) { 967 // Potential match 968 if count[t] > 1 || ok { 969 // Name appeared multiple times at this level: annihilate. 970 return StructField{}, false 971 } 972 result = t.Field(i) 973 result.Index = nil 974 result.Index = append(result.Index, scan.index...) 975 result.Index = append(result.Index, i) 976 ok = true 977 continue 978 } 979 980 // Queue embedded struct fields for processing with next level, 981 // but only if we haven't seen a match yet at this level and only 982 // if the embedded types haven't already been queued. 983 if ok || ntyp == nil || ntyp.Kind() != Struct { 984 continue 985 } 986 ntyp = toType(ntyp).common() 987 styp := (*structType)(unsafe.Pointer(ntyp)) 988 if nextCount[styp] > 0 { 989 nextCount[styp] = 2 // exact multiple doesn't matter 990 continue 991 } 992 if nextCount == nil { 993 nextCount = map[*structType]int{} 994 } 995 nextCount[styp] = 1 996 if count[t] > 1 { 997 nextCount[styp] = 2 // exact multiple doesn't matter 998 } 999 var index []int 1000 index = append(index, scan.index...) 1001 index = append(index, i) 1002 next = append(next, fieldScan{styp, index}) 1003 } 1004 } 1005 if ok { 1006 break 1007 } 1008 } 1009 return 1010 } 1011 1012 // FieldByName returns the struct field with the given name 1013 // and a boolean to indicate if the field was found. 1014 func (t *structType) FieldByName(name string) (f StructField, present bool) { 1015 // Quick check for top-level name, or struct without anonymous fields. 1016 hasAnon := false 1017 if name != "" { 1018 for i := range t.fields { 1019 tf := &t.fields[i] 1020 if tf.name == nil { 1021 hasAnon = true 1022 continue 1023 } 1024 if *tf.name == name { 1025 return t.Field(i), true 1026 } 1027 } 1028 } 1029 if !hasAnon { 1030 return 1031 } 1032 return t.FieldByNameFunc(func(s string) bool { return s == name }) 1033 } 1034 1035 // TypeOf returns the reflection Type that represents the dynamic type of i. 1036 // If i is a nil interface value, TypeOf returns nil. 1037 func TypeOf(i interface{}) Type { 1038 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 1039 return toType(eface.typ) 1040 } 1041 1042 // ptrMap is the cache for PtrTo. 1043 var ptrMap struct { 1044 sync.RWMutex 1045 m map[*rtype]*ptrType 1046 } 1047 1048 // garbage collection bytecode program for pointer to memory without pointers. 1049 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1050 type ptrDataGC struct { 1051 width uintptr // sizeof(ptr) 1052 op uintptr // _GC_APTR 1053 off uintptr // 0 1054 end uintptr // _GC_END 1055 } 1056 1057 var ptrDataGCProg = ptrDataGC{ 1058 width: unsafe.Sizeof((*byte)(nil)), 1059 op: _GC_APTR, 1060 off: 0, 1061 end: _GC_END, 1062 } 1063 1064 // garbage collection bytecode program for pointer to memory with pointers. 1065 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1066 type ptrGC struct { 1067 width uintptr // sizeof(ptr) 1068 op uintptr // _GC_PTR 1069 off uintptr // 0 1070 elemgc unsafe.Pointer // element gc type 1071 end uintptr // _GC_END 1072 } 1073 1074 // PtrTo returns the pointer type with element t. 1075 // For example, if t represents type Foo, PtrTo(t) represents *Foo. 1076 func PtrTo(t Type) Type { 1077 return t.(*rtype).ptrTo() 1078 } 1079 1080 func (t *rtype) ptrTo() *rtype { 1081 if p := t.ptrToThis; p != nil { 1082 return p 1083 } 1084 1085 // Otherwise, synthesize one. 1086 // This only happens for pointers with no methods. 1087 // We keep the mapping in a map on the side, because 1088 // this operation is rare and a separate map lets us keep 1089 // the type structures in read-only memory. 1090 ptrMap.RLock() 1091 if m := ptrMap.m; m != nil { 1092 if p := m[t]; p != nil { 1093 ptrMap.RUnlock() 1094 return &p.rtype 1095 } 1096 } 1097 ptrMap.RUnlock() 1098 ptrMap.Lock() 1099 if ptrMap.m == nil { 1100 ptrMap.m = make(map[*rtype]*ptrType) 1101 } 1102 p := ptrMap.m[t] 1103 if p != nil { 1104 // some other goroutine won the race and created it 1105 ptrMap.Unlock() 1106 return &p.rtype 1107 } 1108 1109 s := "*" + *t.string 1110 1111 canonicalTypeLock.RLock() 1112 r, ok := canonicalType[s] 1113 canonicalTypeLock.RUnlock() 1114 if ok { 1115 ptrMap.m[t] = (*ptrType)(unsafe.Pointer(r.(*rtype))) 1116 ptrMap.Unlock() 1117 return r.(*rtype) 1118 } 1119 1120 // Create a new ptrType starting with the description 1121 // of an *unsafe.Pointer. 1122 p = new(ptrType) 1123 var iptr interface{} = (*unsafe.Pointer)(nil) 1124 prototype := *(**ptrType)(unsafe.Pointer(&iptr)) 1125 *p = *prototype 1126 1127 p.string = &s 1128 1129 // For the type structures linked into the binary, the 1130 // compiler provides a good hash of the string. 1131 // Create a good hash for the new string by using 1132 // the FNV-1 hash's mixing function to combine the 1133 // old hash and the new "*". 1134 // p.hash = fnv1(t.hash, '*') 1135 // This is the gccgo version. 1136 p.hash = (t.hash << 4) + 9 1137 1138 p.uncommonType = nil 1139 p.ptrToThis = nil 1140 p.elem = t 1141 1142 if t.kind&kindNoPointers != 0 { 1143 p.gc = unsafe.Pointer(&ptrDataGCProg) 1144 } else { 1145 p.gc = unsafe.Pointer(&ptrGC{ 1146 width: p.size, 1147 op: _GC_PTR, 1148 off: 0, 1149 elemgc: t.gc, 1150 end: _GC_END, 1151 }) 1152 } 1153 1154 q := canonicalize(&p.rtype) 1155 p = (*ptrType)(unsafe.Pointer(q.(*rtype))) 1156 1157 ptrMap.m[t] = p 1158 ptrMap.Unlock() 1159 return &p.rtype 1160 } 1161 1162 // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function. 1163 func fnv1(x uint32, list ...byte) uint32 { 1164 for _, b := range list { 1165 x = x*16777619 ^ uint32(b) 1166 } 1167 return x 1168 } 1169 1170 func (t *rtype) Implements(u Type) bool { 1171 if u == nil { 1172 panic("reflect: nil type passed to Type.Implements") 1173 } 1174 if u.Kind() != Interface { 1175 panic("reflect: non-interface type passed to Type.Implements") 1176 } 1177 return implements(u.(*rtype), t) 1178 } 1179 1180 func (t *rtype) AssignableTo(u Type) bool { 1181 if u == nil { 1182 panic("reflect: nil type passed to Type.AssignableTo") 1183 } 1184 uu := u.(*rtype) 1185 return directlyAssignable(uu, t) || implements(uu, t) 1186 } 1187 1188 func (t *rtype) ConvertibleTo(u Type) bool { 1189 if u == nil { 1190 panic("reflect: nil type passed to Type.ConvertibleTo") 1191 } 1192 uu := u.(*rtype) 1193 return convertOp(uu, t) != nil 1194 } 1195 1196 func (t *rtype) Comparable() bool { 1197 switch t.Kind() { 1198 case Bool, Int, Int8, Int16, Int32, Int64, 1199 Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, 1200 Float32, Float64, Complex64, Complex128, 1201 Chan, Interface, Ptr, String, UnsafePointer: 1202 return true 1203 1204 case Func, Map, Slice: 1205 return false 1206 1207 case Array: 1208 return (*arrayType)(unsafe.Pointer(t)).elem.Comparable() 1209 1210 case Struct: 1211 tt := (*structType)(unsafe.Pointer(t)) 1212 for i := range tt.fields { 1213 if !tt.fields[i].typ.Comparable() { 1214 return false 1215 } 1216 } 1217 return true 1218 1219 default: 1220 panic("reflect: impossible") 1221 } 1222 } 1223 1224 // implements reports whether the type V implements the interface type T. 1225 func implements(T, V *rtype) bool { 1226 if T.Kind() != Interface { 1227 return false 1228 } 1229 t := (*interfaceType)(unsafe.Pointer(T)) 1230 if len(t.methods) == 0 { 1231 return true 1232 } 1233 1234 // The same algorithm applies in both cases, but the 1235 // method tables for an interface type and a concrete type 1236 // are different, so the code is duplicated. 1237 // In both cases the algorithm is a linear scan over the two 1238 // lists - T's methods and V's methods - simultaneously. 1239 // Since method tables are stored in a unique sorted order 1240 // (alphabetical, with no duplicate method names), the scan 1241 // through V's methods must hit a match for each of T's 1242 // methods along the way, or else V does not implement T. 1243 // This lets us run the scan in overall linear time instead of 1244 // the quadratic time a naive search would require. 1245 // See also ../runtime/iface.go. 1246 if V.Kind() == Interface { 1247 v := (*interfaceType)(unsafe.Pointer(V)) 1248 i := 0 1249 for j := 0; j < len(v.methods); j++ { 1250 tm := &t.methods[i] 1251 vm := &v.methods[j] 1252 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() { 1253 if i++; i >= len(t.methods) { 1254 return true 1255 } 1256 } 1257 } 1258 return false 1259 } 1260 1261 v := V.uncommon() 1262 if v == nil { 1263 return false 1264 } 1265 i := 0 1266 for j := 0; j < len(v.methods); j++ { 1267 tm := &t.methods[i] 1268 vm := &v.methods[j] 1269 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() { 1270 if i++; i >= len(t.methods) { 1271 return true 1272 } 1273 } 1274 } 1275 return false 1276 } 1277 1278 // directlyAssignable reports whether a value x of type V can be directly 1279 // assigned (using memmove) to a value of type T. 1280 // https://golang.org/doc/go_spec.html#Assignability 1281 // Ignoring the interface rules (implemented elsewhere) 1282 // and the ideal constant rules (no ideal constants at run time). 1283 func directlyAssignable(T, V *rtype) bool { 1284 // x's type V is identical to T? 1285 if T == V { 1286 return true 1287 } 1288 1289 // Otherwise at least one of T and V must be unnamed 1290 // and they must have the same kind. 1291 if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() { 1292 return false 1293 } 1294 1295 // x's type T and V must have identical underlying types. 1296 return haveIdenticalUnderlyingType(T, V) 1297 } 1298 1299 func haveIdenticalUnderlyingType(T, V *rtype) bool { 1300 if T == V { 1301 return true 1302 } 1303 1304 kind := T.Kind() 1305 if kind != V.Kind() { 1306 return false 1307 } 1308 1309 // Non-composite types of equal kind have same underlying type 1310 // (the predefined instance of the type). 1311 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer { 1312 return true 1313 } 1314 1315 // Composite types. 1316 switch kind { 1317 case Array: 1318 return T.Elem() == V.Elem() && T.Len() == V.Len() 1319 1320 case Chan: 1321 // Special case: 1322 // x is a bidirectional channel value, T is a channel type, 1323 // and x's type V and T have identical element types. 1324 if V.ChanDir() == BothDir && T.Elem() == V.Elem() { 1325 return true 1326 } 1327 1328 // Otherwise continue test for identical underlying type. 1329 return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem() 1330 1331 case Func: 1332 t := (*funcType)(unsafe.Pointer(T)) 1333 v := (*funcType)(unsafe.Pointer(V)) 1334 if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) { 1335 return false 1336 } 1337 for i, typ := range t.in { 1338 if typ != v.in[i] { 1339 return false 1340 } 1341 } 1342 for i, typ := range t.out { 1343 if typ != v.out[i] { 1344 return false 1345 } 1346 } 1347 return true 1348 1349 case Interface: 1350 t := (*interfaceType)(unsafe.Pointer(T)) 1351 v := (*interfaceType)(unsafe.Pointer(V)) 1352 if len(t.methods) == 0 && len(v.methods) == 0 { 1353 return true 1354 } 1355 // Might have the same methods but still 1356 // need a run time conversion. 1357 return false 1358 1359 case Map: 1360 return T.Key() == V.Key() && T.Elem() == V.Elem() 1361 1362 case Ptr, Slice: 1363 return T.Elem() == V.Elem() 1364 1365 case Struct: 1366 t := (*structType)(unsafe.Pointer(T)) 1367 v := (*structType)(unsafe.Pointer(V)) 1368 if len(t.fields) != len(v.fields) { 1369 return false 1370 } 1371 for i := range t.fields { 1372 tf := &t.fields[i] 1373 vf := &v.fields[i] 1374 if tf.name != vf.name && (tf.name == nil || vf.name == nil || *tf.name != *vf.name) { 1375 return false 1376 } 1377 if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) { 1378 return false 1379 } 1380 if tf.typ != vf.typ { 1381 return false 1382 } 1383 if tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) { 1384 return false 1385 } 1386 if tf.offset != vf.offset { 1387 return false 1388 } 1389 } 1390 return true 1391 } 1392 1393 return false 1394 } 1395 1396 // The lookupCache caches ChanOf, MapOf, and SliceOf lookups. 1397 var lookupCache struct { 1398 sync.RWMutex 1399 m map[cacheKey]*rtype 1400 } 1401 1402 // A cacheKey is the key for use in the lookupCache. 1403 // Four values describe any of the types we are looking for: 1404 // type kind, one or two subtypes, and an extra integer. 1405 type cacheKey struct { 1406 kind Kind 1407 t1 *rtype 1408 t2 *rtype 1409 extra uintptr 1410 } 1411 1412 // cacheGet looks for a type under the key k in the lookupCache. 1413 // If it finds one, it returns that type. 1414 // If not, it returns nil with the cache locked. 1415 // The caller is expected to use cachePut to unlock the cache. 1416 func cacheGet(k cacheKey) Type { 1417 lookupCache.RLock() 1418 t := lookupCache.m[k] 1419 lookupCache.RUnlock() 1420 if t != nil { 1421 return t 1422 } 1423 1424 lookupCache.Lock() 1425 t = lookupCache.m[k] 1426 if t != nil { 1427 lookupCache.Unlock() 1428 return t 1429 } 1430 1431 if lookupCache.m == nil { 1432 lookupCache.m = make(map[cacheKey]*rtype) 1433 } 1434 1435 return nil 1436 } 1437 1438 // cachePut stores the given type in the cache, unlocks the cache, 1439 // and returns the type. It is expected that the cache is locked 1440 // because cacheGet returned nil. 1441 func cachePut(k cacheKey, t *rtype) Type { 1442 t = toType(t).common() 1443 lookupCache.m[k] = t 1444 lookupCache.Unlock() 1445 return t 1446 } 1447 1448 // garbage collection bytecode program for chan. 1449 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1450 type chanGC struct { 1451 width uintptr // sizeof(map) 1452 op uintptr // _GC_CHAN_PTR 1453 off uintptr // 0 1454 typ *rtype // map type 1455 end uintptr // _GC_END 1456 } 1457 1458 // The funcLookupCache caches FuncOf lookups. 1459 // FuncOf does not share the common lookupCache since cacheKey is not 1460 // sufficient to represent functions unambiguously. 1461 var funcLookupCache struct { 1462 sync.RWMutex 1463 m map[uint32][]*rtype // keyed by hash calculated in FuncOf 1464 } 1465 1466 // ChanOf returns the channel type with the given direction and element type. 1467 // For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int. 1468 // 1469 // The gc runtime imposes a limit of 64 kB on channel element types. 1470 // If t's size is equal to or exceeds this limit, ChanOf panics. 1471 func ChanOf(dir ChanDir, t Type) Type { 1472 typ := t.(*rtype) 1473 1474 // Look in cache. 1475 ckey := cacheKey{Chan, typ, nil, uintptr(dir)} 1476 if ch := cacheGet(ckey); ch != nil { 1477 return ch 1478 } 1479 1480 // This restriction is imposed by the gc compiler and the runtime. 1481 if typ.size >= 1<<16 { 1482 lookupCache.Unlock() 1483 panic("reflect.ChanOf: element size too large") 1484 } 1485 1486 // Look in known types. 1487 // TODO: Precedence when constructing string. 1488 var s string 1489 switch dir { 1490 default: 1491 lookupCache.Unlock() 1492 panic("reflect.ChanOf: invalid dir") 1493 case SendDir: 1494 s = "chan<- " + *typ.string 1495 case RecvDir: 1496 s = "<-chan " + *typ.string 1497 case BothDir: 1498 s = "chan " + *typ.string 1499 } 1500 1501 // Make a channel type. 1502 var ichan interface{} = (chan unsafe.Pointer)(nil) 1503 prototype := *(**chanType)(unsafe.Pointer(&ichan)) 1504 ch := new(chanType) 1505 *ch = *prototype 1506 ch.dir = uintptr(dir) 1507 ch.string = &s 1508 1509 // gccgo uses a different hash. 1510 // ch.hash = fnv1(typ.hash, 'c', byte(dir)) 1511 ch.hash = 0 1512 if dir&SendDir != 0 { 1513 ch.hash += 1 1514 } 1515 if dir&RecvDir != 0 { 1516 ch.hash += 2 1517 } 1518 ch.hash += typ.hash << 2 1519 ch.hash <<= 3 1520 ch.hash += 15 1521 1522 ch.elem = typ 1523 ch.uncommonType = nil 1524 ch.ptrToThis = nil 1525 1526 ch.gc = unsafe.Pointer(&chanGC{ 1527 width: ch.size, 1528 op: _GC_CHAN_PTR, 1529 off: 0, 1530 typ: &ch.rtype, 1531 end: _GC_END, 1532 }) 1533 1534 // INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong. 1535 // ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END}) 1536 1537 return cachePut(ckey, &ch.rtype) 1538 } 1539 1540 func ismapkey(*rtype) bool // implemented in runtime 1541 1542 // MapOf returns the map type with the given key and element types. 1543 // For example, if k represents int and e represents string, 1544 // MapOf(k, e) represents map[int]string. 1545 // 1546 // If the key type is not a valid map key type (that is, if it does 1547 // not implement Go's == operator), MapOf panics. 1548 func MapOf(key, elem Type) Type { 1549 ktyp := key.(*rtype) 1550 etyp := elem.(*rtype) 1551 1552 if !ismapkey(ktyp) { 1553 panic("reflect.MapOf: invalid key type " + ktyp.String()) 1554 } 1555 1556 // Look in cache. 1557 ckey := cacheKey{Map, ktyp, etyp, 0} 1558 if mt := cacheGet(ckey); mt != nil { 1559 return mt 1560 } 1561 1562 // Look in known types. 1563 s := "map[" + *ktyp.string + "]" + *etyp.string 1564 1565 // Make a map type. 1566 var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) 1567 mt := new(mapType) 1568 *mt = **(**mapType)(unsafe.Pointer(&imap)) 1569 mt.string = &s 1570 1571 // gccgo uses a different hash 1572 // mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash)) 1573 mt.hash = ktyp.hash + etyp.hash + 2 + 14 1574 1575 mt.key = ktyp 1576 mt.elem = etyp 1577 mt.uncommonType = nil 1578 mt.ptrToThis = nil 1579 // mt.gc = unsafe.Pointer(&ptrGC{ 1580 // width: unsafe.Sizeof(uintptr(0)), 1581 // op: _GC_PTR, 1582 // off: 0, 1583 // elemgc: nil, 1584 // end: _GC_END, 1585 // }) 1586 1587 // TODO(cmang): Generate GC data for Map elements. 1588 mt.gc = unsafe.Pointer(&ptrDataGCProg) 1589 1590 // INCORRECT. Uncomment to check that TestMapOfGC and TestMapOfGCValues 1591 // fail when mt.gc is wrong. 1592 //mt.gc = unsafe.Pointer(&badGC{width: mt.size, end: _GC_END}) 1593 1594 return cachePut(ckey, &mt.rtype) 1595 } 1596 1597 // FuncOf returns the function type with the given argument and result types. 1598 // For example if k represents int and e represents string, 1599 // FuncOf([]Type{k}, []Type{e}, false) represents func(int) string. 1600 // 1601 // The variadic argument controls whether the function is variadic. FuncOf 1602 // panics if the in[len(in)-1] does not represent a slice and variadic is 1603 // true. 1604 func FuncOf(in, out []Type, variadic bool) Type { 1605 if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) { 1606 panic("reflect.FuncOf: last arg of variadic func must be slice") 1607 } 1608 1609 // Make a func type. 1610 var ifunc interface{} = (func())(nil) 1611 prototype := *(**funcType)(unsafe.Pointer(&ifunc)) 1612 ft := new(funcType) 1613 *ft = *prototype 1614 1615 // Build a hash and minimally populate ft. 1616 var hash uint32 = 8 1617 var fin, fout []*rtype 1618 shift := uint(1) 1619 for _, in := range in { 1620 t := in.(*rtype) 1621 fin = append(fin, t) 1622 hash += t.hash << shift 1623 shift++ 1624 } 1625 shift = 2 1626 for _, out := range out { 1627 t := out.(*rtype) 1628 fout = append(fout, t) 1629 hash += t.hash << shift 1630 shift++ 1631 } 1632 if variadic { 1633 hash++ 1634 } 1635 hash <<= 4 1636 ft.hash = hash 1637 ft.in = fin 1638 ft.out = fout 1639 ft.dotdotdot = variadic 1640 1641 // Look in cache. 1642 funcLookupCache.RLock() 1643 for _, t := range funcLookupCache.m[hash] { 1644 if haveIdenticalUnderlyingType(&ft.rtype, t) { 1645 funcLookupCache.RUnlock() 1646 return t 1647 } 1648 } 1649 funcLookupCache.RUnlock() 1650 1651 // Not in cache, lock and retry. 1652 funcLookupCache.Lock() 1653 defer funcLookupCache.Unlock() 1654 if funcLookupCache.m == nil { 1655 funcLookupCache.m = make(map[uint32][]*rtype) 1656 } 1657 for _, t := range funcLookupCache.m[hash] { 1658 if haveIdenticalUnderlyingType(&ft.rtype, t) { 1659 return t 1660 } 1661 } 1662 1663 str := funcStr(ft) 1664 1665 // Populate the remaining fields of ft and store in cache. 1666 ft.string = &str 1667 ft.uncommonType = nil 1668 ft.ptrToThis = nil 1669 1670 // TODO(cmang): Generate GC data for funcs. 1671 ft.gc = unsafe.Pointer(&ptrDataGCProg) 1672 1673 funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype) 1674 1675 return toType(&ft.rtype) 1676 } 1677 1678 // funcStr builds a string representation of a funcType. 1679 func funcStr(ft *funcType) string { 1680 repr := make([]byte, 0, 64) 1681 repr = append(repr, "func("...) 1682 for i, t := range ft.in { 1683 if i > 0 { 1684 repr = append(repr, ", "...) 1685 } 1686 if ft.dotdotdot && i == len(ft.in)-1 { 1687 repr = append(repr, "..."...) 1688 repr = append(repr, *(*sliceType)(unsafe.Pointer(t)).elem.string...) 1689 } else { 1690 repr = append(repr, *t.string...) 1691 } 1692 } 1693 repr = append(repr, ')') 1694 if l := len(ft.out); l == 1 { 1695 repr = append(repr, ' ') 1696 } else if l > 1 { 1697 repr = append(repr, " ("...) 1698 } 1699 for i, t := range ft.out { 1700 if i > 0 { 1701 repr = append(repr, ", "...) 1702 } 1703 repr = append(repr, *t.string...) 1704 } 1705 if len(ft.out) > 1 { 1706 repr = append(repr, ')') 1707 } 1708 return string(repr) 1709 } 1710 1711 // isReflexive reports whether the == operation on the type is reflexive. 1712 // That is, x == x for all values x of type t. 1713 func isReflexive(t *rtype) bool { 1714 switch t.Kind() { 1715 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, String, UnsafePointer: 1716 return true 1717 case Float32, Float64, Complex64, Complex128, Interface: 1718 return false 1719 case Array: 1720 tt := (*arrayType)(unsafe.Pointer(t)) 1721 return isReflexive(tt.elem) 1722 case Struct: 1723 tt := (*structType)(unsafe.Pointer(t)) 1724 for _, f := range tt.fields { 1725 if !isReflexive(f.typ) { 1726 return false 1727 } 1728 } 1729 return true 1730 default: 1731 // Func, Map, Slice, Invalid 1732 panic("isReflexive called on non-key type " + t.String()) 1733 } 1734 } 1735 1736 // Make sure these routines stay in sync with ../../runtime/hashmap.go! 1737 // These types exist only for GC, so we only fill out GC relevant info. 1738 // Currently, that's just size and the GC program. We also fill in string 1739 // for possible debugging use. 1740 const ( 1741 bucketSize uintptr = 8 1742 maxKeySize uintptr = 128 1743 maxValSize uintptr = 128 1744 ) 1745 1746 func bucketOf(ktyp, etyp *rtype) *rtype { 1747 // See comment on hmap.overflow in ../runtime/hashmap.go. 1748 var kind uint8 1749 if ktyp.kind&kindNoPointers != 0 && etyp.kind&kindNoPointers != 0 && 1750 ktyp.size <= maxKeySize && etyp.size <= maxValSize { 1751 kind = kindNoPointers 1752 } 1753 1754 if ktyp.size > maxKeySize { 1755 ktyp = PtrTo(ktyp).(*rtype) 1756 } 1757 if etyp.size > maxValSize { 1758 etyp = PtrTo(etyp).(*rtype) 1759 } 1760 1761 // Prepare GC data if any. 1762 // A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+2*ptrSize bytes, 1763 // or 2072 bytes, or 259 pointer-size words, or 33 bytes of pointer bitmap. 1764 // Normally the enforced limit on pointer maps is 16 bytes, 1765 // but larger ones are acceptable, 33 bytes isn't too too big, 1766 // and it's easier to generate a pointer bitmap than a GC program. 1767 // Note that since the key and value are known to be <= 128 bytes, 1768 // they're guaranteed to have bitmaps instead of GC programs. 1769 // var gcdata *byte 1770 var ptrdata uintptr 1771 var overflowPad uintptr 1772 1773 // On NaCl, pad if needed to make overflow end at the proper struct alignment. 1774 // On other systems, align > ptrSize is not possible. 1775 if runtime.GOARCH == "amd64p32" && (ktyp.align > ptrSize || etyp.align > ptrSize) { 1776 overflowPad = ptrSize 1777 } 1778 size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + ptrSize 1779 if size&uintptr(ktyp.align-1) != 0 || size&uintptr(etyp.align-1) != 0 { 1780 panic("reflect: bad size computation in MapOf") 1781 } 1782 1783 if kind != kindNoPointers { 1784 nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize 1785 mask := make([]byte, (nptr+7)/8) 1786 base := bucketSize / ptrSize 1787 1788 if ktyp.kind&kindNoPointers == 0 { 1789 if ktyp.kind&kindGCProg != 0 { 1790 panic("reflect: unexpected GC program in MapOf") 1791 } 1792 kmask := (*[16]byte)(unsafe.Pointer( /*ktyp.gcdata*/ nil)) 1793 for i := uintptr(0); i < ktyp.size/ptrSize; i++ { 1794 if (kmask[i/8]>>(i%8))&1 != 0 { 1795 for j := uintptr(0); j < bucketSize; j++ { 1796 word := base + j*ktyp.size/ptrSize + i 1797 mask[word/8] |= 1 << (word % 8) 1798 } 1799 } 1800 } 1801 } 1802 base += bucketSize * ktyp.size / ptrSize 1803 1804 if etyp.kind&kindNoPointers == 0 { 1805 if etyp.kind&kindGCProg != 0 { 1806 panic("reflect: unexpected GC program in MapOf") 1807 } 1808 emask := (*[16]byte)(unsafe.Pointer( /*etyp.gcdata*/ nil)) 1809 for i := uintptr(0); i < etyp.size/ptrSize; i++ { 1810 if (emask[i/8]>>(i%8))&1 != 0 { 1811 for j := uintptr(0); j < bucketSize; j++ { 1812 word := base + j*etyp.size/ptrSize + i 1813 mask[word/8] |= 1 << (word % 8) 1814 } 1815 } 1816 } 1817 } 1818 base += bucketSize * etyp.size / ptrSize 1819 base += overflowPad / ptrSize 1820 1821 word := base 1822 mask[word/8] |= 1 << (word % 8) 1823 // gcdata = &mask[0] 1824 ptrdata = (word + 1) * ptrSize 1825 1826 // overflow word must be last 1827 if ptrdata != size { 1828 panic("reflect: bad layout computation in MapOf") 1829 } 1830 } 1831 1832 b := new(rtype) 1833 // b.size = gc.size 1834 // b.gc[0], _ = gc.finalize() 1835 b.kind |= kindGCProg 1836 s := "bucket(" + *ktyp.string + "," + *etyp.string + ")" 1837 b.string = &s 1838 return b 1839 } 1840 1841 // Take the GC program for "t" and append it to the GC program "gc". 1842 func appendGCProgram(gc []uintptr, t *rtype) []uintptr { 1843 p := t.gc 1844 p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size 1845 loop: 1846 for { 1847 var argcnt int 1848 switch *(*uintptr)(p) { 1849 case _GC_END: 1850 // Note: _GC_END not included in append 1851 break loop 1852 case _GC_ARRAY_NEXT: 1853 argcnt = 0 1854 case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE: 1855 argcnt = 1 1856 case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE: 1857 argcnt = 2 1858 case _GC_ARRAY_START, _GC_REGION: 1859 argcnt = 3 1860 default: 1861 panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10)) 1862 } 1863 for i := 0; i < argcnt+1; i++ { 1864 gc = append(gc, *(*uintptr)(p)) 1865 p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) 1866 } 1867 } 1868 return gc 1869 } 1870 func hMapOf(bucket *rtype) *rtype { 1871 ptrsize := unsafe.Sizeof(uintptr(0)) 1872 1873 // make gc program & compute hmap size 1874 gc := make([]uintptr, 1) // first entry is size, filled in at the end 1875 offset := unsafe.Sizeof(uint(0)) // count 1876 offset += unsafe.Sizeof(uint32(0)) // flags 1877 offset += unsafe.Sizeof(uint32(0)) // hash0 1878 offset += unsafe.Sizeof(uint8(0)) // B 1879 offset += unsafe.Sizeof(uint8(0)) // keysize 1880 offset += unsafe.Sizeof(uint8(0)) // valuesize 1881 offset = (offset + 1) / 2 * 2 1882 offset += unsafe.Sizeof(uint16(0)) // bucketsize 1883 offset = (offset + ptrsize - 1) / ptrsize * ptrsize 1884 // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets 1885 offset += ptrsize 1886 // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets 1887 offset += ptrsize 1888 offset += ptrsize // nevacuate 1889 gc = append(gc, _GC_END) 1890 gc[0] = offset 1891 1892 h := new(rtype) 1893 h.size = offset 1894 // h.gc = unsafe.Pointer(&gc[0]) 1895 s := "hmap(" + *bucket.string + ")" 1896 h.string = &s 1897 return h 1898 } 1899 1900 // garbage collection bytecode program for slice of non-zero-length values. 1901 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1902 type sliceGC struct { 1903 width uintptr // sizeof(slice) 1904 op uintptr // _GC_SLICE 1905 off uintptr // 0 1906 elemgc unsafe.Pointer // element gc program 1907 end uintptr // _GC_END 1908 } 1909 1910 // garbage collection bytecode program for slice of zero-length values. 1911 // See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1912 type sliceEmptyGC struct { 1913 width uintptr // sizeof(slice) 1914 op uintptr // _GC_APTR 1915 off uintptr // 0 1916 end uintptr // _GC_END 1917 } 1918 1919 var sliceEmptyGCProg = sliceEmptyGC{ 1920 width: unsafe.Sizeof([]byte(nil)), 1921 op: _GC_APTR, 1922 off: 0, 1923 end: _GC_END, 1924 } 1925 1926 // SliceOf returns the slice type with element type t. 1927 // For example, if t represents int, SliceOf(t) represents []int. 1928 func SliceOf(t Type) Type { 1929 typ := t.(*rtype) 1930 1931 // Look in cache. 1932 ckey := cacheKey{Slice, typ, nil, 0} 1933 if slice := cacheGet(ckey); slice != nil { 1934 return slice 1935 } 1936 1937 // Look in known types. 1938 s := "[]" + *typ.string 1939 1940 // Make a slice type. 1941 var islice interface{} = ([]unsafe.Pointer)(nil) 1942 prototype := *(**sliceType)(unsafe.Pointer(&islice)) 1943 slice := new(sliceType) 1944 *slice = *prototype 1945 slice.string = &s 1946 1947 // gccgo uses a different hash. 1948 // slice.hash = fnv1(typ.hash, '[') 1949 slice.hash = typ.hash + 1 + 13 1950 1951 slice.elem = typ 1952 slice.uncommonType = nil 1953 slice.ptrToThis = nil 1954 1955 if typ.size == 0 { 1956 slice.gc = unsafe.Pointer(&sliceEmptyGCProg) 1957 } else { 1958 slice.gc = unsafe.Pointer(&sliceGC{ 1959 width: slice.size, 1960 op: _GC_SLICE, 1961 off: 0, 1962 elemgc: typ.gc, 1963 end: _GC_END, 1964 }) 1965 } 1966 1967 // INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong. 1968 // slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END}) 1969 1970 return cachePut(ckey, &slice.rtype) 1971 } 1972 1973 // See cmd/compile/internal/gc/reflect.go for derivation of constant. 1974 const maxPtrmaskBytes = 2048 1975 1976 // ArrayOf returns the array type with the given count and element type. 1977 // For example, if t represents int, ArrayOf(5, t) represents [5]int. 1978 // 1979 // If the resulting type would be larger than the available address space, 1980 // ArrayOf panics. 1981 func ArrayOf(count int, elem Type) Type { 1982 typ := elem.(*rtype) 1983 // call SliceOf here as it calls cacheGet/cachePut. 1984 // ArrayOf also calls cacheGet/cachePut and thus may modify the state of 1985 // the lookupCache mutex. 1986 slice := SliceOf(elem) 1987 1988 // Look in cache. 1989 ckey := cacheKey{Array, typ, nil, uintptr(count)} 1990 if array := cacheGet(ckey); array != nil { 1991 return array 1992 } 1993 1994 // Look in known types. 1995 s := "[" + strconv.Itoa(count) + "]" + *typ.string 1996 1997 // Make an array type. 1998 var iarray interface{} = [1]unsafe.Pointer{} 1999 prototype := *(**arrayType)(unsafe.Pointer(&iarray)) 2000 array := new(arrayType) 2001 *array = *prototype 2002 array.string = &s 2003 2004 // gccgo uses a different hash. 2005 // array.hash = fnv1(typ.hash, '[') 2006 // for n := uint32(count); n > 0; n >>= 8 { 2007 // array.hash = fnv1(array.hash, byte(n)) 2008 // } 2009 // array.hash = fnv1(array.hash, ']') 2010 array.hash = typ.hash + 1 + 13 2011 2012 array.elem = typ 2013 max := ^uintptr(0) / typ.size 2014 if uintptr(count) > max { 2015 panic("reflect.ArrayOf: array size would exceed virtual address space") 2016 } 2017 array.size = typ.size * uintptr(count) 2018 // if count > 0 && typ.ptrdata != 0 { 2019 // array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata 2020 // } 2021 array.align = typ.align 2022 array.fieldAlign = typ.fieldAlign 2023 array.uncommonType = nil 2024 array.ptrToThis = nil 2025 array.len = uintptr(count) 2026 array.slice = slice.(*rtype) 2027 2028 array.kind &^= kindNoPointers 2029 switch { 2030 case typ.kind&kindNoPointers != 0 || array.size == 0: 2031 // No pointers. 2032 array.kind |= kindNoPointers 2033 gc := [...]uintptr{array.size, _GC_END} 2034 array.gc = unsafe.Pointer(&gc[0]) 2035 2036 case count == 1: 2037 // In memory, 1-element array looks just like the element. 2038 array.kind |= typ.kind & kindGCProg 2039 array.gc = typ.gc 2040 2041 default: 2042 gc := []uintptr{array.size, _GC_ARRAY_START, 0, uintptr(count), typ.size} 2043 gc = appendGCProgram(gc, typ) 2044 gc = append(gc, _GC_ARRAY_NEXT, _GC_END) 2045 array.gc = unsafe.Pointer(&gc[0]) 2046 } 2047 2048 array.kind &^= kindDirectIface 2049 2050 array.hashfn = func(p unsafe.Pointer, size uintptr) uintptr { 2051 ret := uintptr(0) 2052 for i := 0; i < count; i++ { 2053 ret *= 33 2054 ret += typ.hashfn(p, typ.size) 2055 p = unsafe.Pointer(uintptr(p) + typ.size) 2056 } 2057 return ret 2058 } 2059 2060 array.equalfn = func(p1, p2 unsafe.Pointer, size uintptr) bool { 2061 for i := 0; i < count; i++ { 2062 if !typ.equalfn(p1, p2, typ.size) { 2063 return false 2064 } 2065 p1 = unsafe.Pointer(uintptr(p1) + typ.size) 2066 p2 = unsafe.Pointer(uintptr(p2) + typ.size) 2067 } 2068 return true 2069 } 2070 2071 return cachePut(ckey, &array.rtype) 2072 } 2073 2074 func appendVarint(x []byte, v uintptr) []byte { 2075 for ; v >= 0x80; v >>= 7 { 2076 x = append(x, byte(v|0x80)) 2077 } 2078 x = append(x, byte(v)) 2079 return x 2080 } 2081 2082 // toType converts from a *rtype to a Type that can be returned 2083 // to the client of package reflect. In gc, the only concern is that 2084 // a nil *rtype must be replaced by a nil Type, but in gccgo this 2085 // function takes care of ensuring that multiple *rtype for the same 2086 // type are coalesced into a single Type. 2087 var canonicalType = make(map[string]Type) 2088 2089 var canonicalTypeLock sync.RWMutex 2090 2091 func canonicalize(t Type) Type { 2092 if t == nil { 2093 return nil 2094 } 2095 s := t.rawString() 2096 canonicalTypeLock.RLock() 2097 if r, ok := canonicalType[s]; ok { 2098 canonicalTypeLock.RUnlock() 2099 return r 2100 } 2101 canonicalTypeLock.RUnlock() 2102 canonicalTypeLock.Lock() 2103 if r, ok := canonicalType[s]; ok { 2104 canonicalTypeLock.Unlock() 2105 return r 2106 } 2107 canonicalType[s] = t 2108 canonicalTypeLock.Unlock() 2109 return t 2110 } 2111 2112 func toType(p *rtype) Type { 2113 if p == nil { 2114 return nil 2115 } 2116 return canonicalize(p) 2117 } 2118 2119 // ifaceIndir reports whether t is stored indirectly in an interface value. 2120 func ifaceIndir(t *rtype) bool { 2121 return t.kind&kindDirectIface == 0 2122 } 2123 2124 // Layout matches runtime.BitVector (well enough). 2125 type bitVector struct { 2126 n uint32 // number of bits 2127 data []byte 2128 } 2129 2130 // append a bit to the bitmap. 2131 func (bv *bitVector) append(bit uint8) { 2132 if bv.n%8 == 0 { 2133 bv.data = append(bv.data, 0) 2134 } 2135 bv.data[bv.n/8] |= bit << (bv.n % 8) 2136 bv.n++ 2137 } 2138 2139 func addTypeBits(bv *bitVector, offset uintptr, t *rtype) { 2140 if t.kind&kindNoPointers != 0 { 2141 return 2142 } 2143 2144 switch Kind(t.kind & kindMask) { 2145 case Chan, Func, Map, Ptr, Slice, String, UnsafePointer: 2146 // 1 pointer at start of representation 2147 for bv.n < uint32(offset/uintptr(ptrSize)) { 2148 bv.append(0) 2149 } 2150 bv.append(1) 2151 2152 case Interface: 2153 // 2 pointers 2154 for bv.n < uint32(offset/uintptr(ptrSize)) { 2155 bv.append(0) 2156 } 2157 bv.append(1) 2158 bv.append(1) 2159 2160 case Array: 2161 // repeat inner type 2162 tt := (*arrayType)(unsafe.Pointer(t)) 2163 for i := 0; i < int(tt.len); i++ { 2164 addTypeBits(bv, offset+uintptr(i)*tt.elem.size, tt.elem) 2165 } 2166 2167 case Struct: 2168 // apply fields 2169 tt := (*structType)(unsafe.Pointer(t)) 2170 for i := range tt.fields { 2171 f := &tt.fields[i] 2172 addTypeBits(bv, offset+f.offset, f.typ) 2173 } 2174 } 2175 }