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 16package reflect 17 18import ( 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. 32type 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. 214type Kind uint 215 216const ( 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. 250type 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 268type 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. 280type 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. 287type ChanDir int 288 289const ( 290 RecvDir ChanDir = 1 << iota // <-chan 291 SendDir // chan<- 292 BothDir = RecvDir | SendDir // chan 293) 294 295// arrayType represents a fixed array type. 296type 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. 304type 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. 311type 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 319type 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. 326type interfaceType struct { 327 rtype `reflect:"interface"` 328 methods []imethod // sorted by hash 329} 330 331// mapType represents a map type. 332type 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. 339type ptrType struct { 340 rtype `reflect:"ptr"` 341 elem *rtype // pointer element (pointed at) type 342} 343 344// sliceType represents a slice type. 345type sliceType struct { 346 rtype `reflect:"slice"` 347 elem *rtype // slice element type 348} 349 350// Struct field 351type 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. 360type 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. 367const ( 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. 389type 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 404const ( 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 411func (k Kind) String() string { 412 if int(k) < len(kindNames) { 413 return kindNames[k] 414 } 415 return "kind" + strconv.Itoa(int(k)) 416} 417 418var 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 448func (t *uncommonType) uncommon() *uncommonType { 449 return t 450} 451 452func (t *uncommonType) PkgPath() string { 453 if t == nil || t.pkgPath == nil { 454 return "" 455 } 456 return *t.pkgPath 457} 458 459func (t *uncommonType) Name() string { 460 if t == nil || t.name == nil { 461 return "" 462 } 463 return *t.name 464} 465 466func (t *rtype) rawString() string { return *t.string } 467 468func (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 485func (t *rtype) Size() uintptr { return t.size } 486 487func (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 498func (t *rtype) Align() int { return int(t.align) } 499 500func (t *rtype) FieldAlign() int { return int(t.fieldAlign) } 501 502func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) } 503 504func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 } 505 506func (t *rtype) common() *rtype { return t } 507 508func (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 530func (t *uncommonType) NumMethod() int { 531 if t == nil { 532 return 0 533 } 534 return len(t.methods) 535} 536 537func (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. 554func (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 562func (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 570func (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 578func (t *rtype) PkgPath() string { 579 return t.uncommonType.PkgPath() 580} 581 582func (t *rtype) Name() string { 583 return t.uncommonType.Name() 584} 585 586func (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 594func (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 602func (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 623func (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 631func (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 639func (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 647func (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 655func (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 663func (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 671func (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 679func (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 687func (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 695func (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 703func (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 711func (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. 724func (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. 739func (t *interfaceType) NumMethod() int { return len(t.methods) } 740 741// MethodByName method with the given name in the type's method set. 742func (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. 757type StructField struct { 758 // Name is the field name. 759 Name string 760 // PkgPath is the package path that qualifies a lower case (unexported) 761 // field name. It is empty for upper case (exported) field names. 762 // See https://golang.org/ref/spec#Uniqueness_of_identifiers 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. 780type 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. 786func (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. 841func (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. 880func (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. 896type 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. 903func (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. 1014func (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. 1037func TypeOf(i interface{}) Type { 1038 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 1039 return toType(eface.typ) 1040} 1041 1042// ptrMap is the cache for PtrTo. 1043var 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. 1050type ptrDataGC struct { 1051 width uintptr // sizeof(ptr) 1052 op uintptr // _GC_APTR 1053 off uintptr // 0 1054 end uintptr // _GC_END 1055} 1056 1057var 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. 1066type 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. 1076func PtrTo(t Type) Type { 1077 return t.(*rtype).ptrTo() 1078} 1079 1080func (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. 1163func fnv1(x uint32, list ...byte) uint32 { 1164 for _, b := range list { 1165 x = x*16777619 ^ uint32(b) 1166 } 1167 return x 1168} 1169 1170func (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 1180func (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 1188func (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 1196func (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. 1225func 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). 1283func 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 1299func 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. 1397var 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. 1405type 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. 1416func 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. 1441func 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. 1450type 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. 1461var 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. 1471func 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 1540func 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. 1548func 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. 1604func 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. 1679func 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. 1713func 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// needKeyUpdate reports whether map overwrites require the key to be copied. 1737func needKeyUpdate(t *rtype) bool { 1738 switch t.Kind() { 1739 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, UnsafePointer: 1740 return false 1741 case Float32, Float64, Complex64, Complex128, Interface, String: 1742 // Float keys can be updated from +0 to -0. 1743 // String keys can be updated to use a smaller backing store. 1744 // Interfaces might have floats of strings in them. 1745 return true 1746 case Array: 1747 tt := (*arrayType)(unsafe.Pointer(t)) 1748 return needKeyUpdate(tt.elem) 1749 case Struct: 1750 tt := (*structType)(unsafe.Pointer(t)) 1751 for _, f := range tt.fields { 1752 if needKeyUpdate(f.typ) { 1753 return true 1754 } 1755 } 1756 return false 1757 default: 1758 // Func, Map, Slice, Invalid 1759 panic("needKeyUpdate called on non-key type " + t.String()) 1760 } 1761} 1762 1763// Make sure these routines stay in sync with ../../runtime/hashmap.go! 1764// These types exist only for GC, so we only fill out GC relevant info. 1765// Currently, that's just size and the GC program. We also fill in string 1766// for possible debugging use. 1767const ( 1768 bucketSize uintptr = 8 1769 maxKeySize uintptr = 128 1770 maxValSize uintptr = 128 1771) 1772 1773func bucketOf(ktyp, etyp *rtype) *rtype { 1774 // See comment on hmap.overflow in ../runtime/hashmap.go. 1775 var kind uint8 1776 if ktyp.kind&kindNoPointers != 0 && etyp.kind&kindNoPointers != 0 && 1777 ktyp.size <= maxKeySize && etyp.size <= maxValSize { 1778 kind = kindNoPointers 1779 } 1780 1781 if ktyp.size > maxKeySize { 1782 ktyp = PtrTo(ktyp).(*rtype) 1783 } 1784 if etyp.size > maxValSize { 1785 etyp = PtrTo(etyp).(*rtype) 1786 } 1787 1788 // Prepare GC data if any. 1789 // A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+2*ptrSize bytes, 1790 // or 2072 bytes, or 259 pointer-size words, or 33 bytes of pointer bitmap. 1791 // Normally the enforced limit on pointer maps is 16 bytes, 1792 // but larger ones are acceptable, 33 bytes isn't too too big, 1793 // and it's easier to generate a pointer bitmap than a GC program. 1794 // Note that since the key and value are known to be <= 128 bytes, 1795 // they're guaranteed to have bitmaps instead of GC programs. 1796 // var gcdata *byte 1797 var ptrdata uintptr 1798 var overflowPad uintptr 1799 1800 // On NaCl, pad if needed to make overflow end at the proper struct alignment. 1801 // On other systems, align > ptrSize is not possible. 1802 if runtime.GOARCH == "amd64p32" && (ktyp.align > ptrSize || etyp.align > ptrSize) { 1803 overflowPad = ptrSize 1804 } 1805 size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + ptrSize 1806 if size&uintptr(ktyp.align-1) != 0 || size&uintptr(etyp.align-1) != 0 { 1807 panic("reflect: bad size computation in MapOf") 1808 } 1809 1810 if kind != kindNoPointers { 1811 nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize 1812 mask := make([]byte, (nptr+7)/8) 1813 base := bucketSize / ptrSize 1814 1815 if ktyp.kind&kindNoPointers == 0 { 1816 if ktyp.kind&kindGCProg != 0 { 1817 panic("reflect: unexpected GC program in MapOf") 1818 } 1819 kmask := (*[16]byte)(unsafe.Pointer( /*ktyp.gcdata*/ nil)) 1820 for i := uintptr(0); i < ktyp.size/ptrSize; i++ { 1821 if (kmask[i/8]>>(i%8))&1 != 0 { 1822 for j := uintptr(0); j < bucketSize; j++ { 1823 word := base + j*ktyp.size/ptrSize + i 1824 mask[word/8] |= 1 << (word % 8) 1825 } 1826 } 1827 } 1828 } 1829 base += bucketSize * ktyp.size / ptrSize 1830 1831 if etyp.kind&kindNoPointers == 0 { 1832 if etyp.kind&kindGCProg != 0 { 1833 panic("reflect: unexpected GC program in MapOf") 1834 } 1835 emask := (*[16]byte)(unsafe.Pointer( /*etyp.gcdata*/ nil)) 1836 for i := uintptr(0); i < etyp.size/ptrSize; i++ { 1837 if (emask[i/8]>>(i%8))&1 != 0 { 1838 for j := uintptr(0); j < bucketSize; j++ { 1839 word := base + j*etyp.size/ptrSize + i 1840 mask[word/8] |= 1 << (word % 8) 1841 } 1842 } 1843 } 1844 } 1845 base += bucketSize * etyp.size / ptrSize 1846 base += overflowPad / ptrSize 1847 1848 word := base 1849 mask[word/8] |= 1 << (word % 8) 1850 // gcdata = &mask[0] 1851 ptrdata = (word + 1) * ptrSize 1852 1853 // overflow word must be last 1854 if ptrdata != size { 1855 panic("reflect: bad layout computation in MapOf") 1856 } 1857 } 1858 1859 b := new(rtype) 1860 // b.size = gc.size 1861 // b.gc[0], _ = gc.finalize() 1862 b.kind |= kindGCProg 1863 s := "bucket(" + *ktyp.string + "," + *etyp.string + ")" 1864 b.string = &s 1865 return b 1866} 1867 1868// Take the GC program for "t" and append it to the GC program "gc". 1869func appendGCProgram(gc []uintptr, t *rtype) []uintptr { 1870 p := t.gc 1871 p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size 1872loop: 1873 for { 1874 var argcnt int 1875 switch *(*uintptr)(p) { 1876 case _GC_END: 1877 // Note: _GC_END not included in append 1878 break loop 1879 case _GC_ARRAY_NEXT: 1880 argcnt = 0 1881 case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE: 1882 argcnt = 1 1883 case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE: 1884 argcnt = 2 1885 case _GC_ARRAY_START, _GC_REGION: 1886 argcnt = 3 1887 default: 1888 panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10)) 1889 } 1890 for i := 0; i < argcnt+1; i++ { 1891 gc = append(gc, *(*uintptr)(p)) 1892 p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) 1893 } 1894 } 1895 return gc 1896} 1897func hMapOf(bucket *rtype) *rtype { 1898 ptrsize := unsafe.Sizeof(uintptr(0)) 1899 1900 // make gc program & compute hmap size 1901 gc := make([]uintptr, 1) // first entry is size, filled in at the end 1902 offset := unsafe.Sizeof(uint(0)) // count 1903 offset += unsafe.Sizeof(uint32(0)) // flags 1904 offset += unsafe.Sizeof(uint32(0)) // hash0 1905 offset += unsafe.Sizeof(uint8(0)) // B 1906 offset += unsafe.Sizeof(uint8(0)) // keysize 1907 offset += unsafe.Sizeof(uint8(0)) // valuesize 1908 offset = (offset + 1) / 2 * 2 1909 offset += unsafe.Sizeof(uint16(0)) // bucketsize 1910 offset = (offset + ptrsize - 1) / ptrsize * ptrsize 1911 // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets 1912 offset += ptrsize 1913 // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets 1914 offset += ptrsize 1915 offset += ptrsize // nevacuate 1916 gc = append(gc, _GC_END) 1917 gc[0] = offset 1918 1919 h := new(rtype) 1920 h.size = offset 1921 // h.gc = unsafe.Pointer(&gc[0]) 1922 s := "hmap(" + *bucket.string + ")" 1923 h.string = &s 1924 return h 1925} 1926 1927// garbage collection bytecode program for slice of non-zero-length values. 1928// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1929type sliceGC struct { 1930 width uintptr // sizeof(slice) 1931 op uintptr // _GC_SLICE 1932 off uintptr // 0 1933 elemgc unsafe.Pointer // element gc program 1934 end uintptr // _GC_END 1935} 1936 1937// garbage collection bytecode program for slice of zero-length values. 1938// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym. 1939type sliceEmptyGC struct { 1940 width uintptr // sizeof(slice) 1941 op uintptr // _GC_APTR 1942 off uintptr // 0 1943 end uintptr // _GC_END 1944} 1945 1946var sliceEmptyGCProg = sliceEmptyGC{ 1947 width: unsafe.Sizeof([]byte(nil)), 1948 op: _GC_APTR, 1949 off: 0, 1950 end: _GC_END, 1951} 1952 1953// SliceOf returns the slice type with element type t. 1954// For example, if t represents int, SliceOf(t) represents []int. 1955func SliceOf(t Type) Type { 1956 typ := t.(*rtype) 1957 1958 // Look in cache. 1959 ckey := cacheKey{Slice, typ, nil, 0} 1960 if slice := cacheGet(ckey); slice != nil { 1961 return slice 1962 } 1963 1964 // Look in known types. 1965 s := "[]" + *typ.string 1966 1967 // Make a slice type. 1968 var islice interface{} = ([]unsafe.Pointer)(nil) 1969 prototype := *(**sliceType)(unsafe.Pointer(&islice)) 1970 slice := new(sliceType) 1971 *slice = *prototype 1972 slice.string = &s 1973 1974 // gccgo uses a different hash. 1975 // slice.hash = fnv1(typ.hash, '[') 1976 slice.hash = typ.hash + 1 + 13 1977 1978 slice.elem = typ 1979 slice.uncommonType = nil 1980 slice.ptrToThis = nil 1981 1982 if typ.size == 0 { 1983 slice.gc = unsafe.Pointer(&sliceEmptyGCProg) 1984 } else { 1985 slice.gc = unsafe.Pointer(&sliceGC{ 1986 width: slice.size, 1987 op: _GC_SLICE, 1988 off: 0, 1989 elemgc: typ.gc, 1990 end: _GC_END, 1991 }) 1992 } 1993 1994 // INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong. 1995 // slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END}) 1996 1997 return cachePut(ckey, &slice.rtype) 1998} 1999 2000// See cmd/compile/internal/gc/reflect.go for derivation of constant. 2001const maxPtrmaskBytes = 2048 2002 2003// ArrayOf returns the array type with the given count and element type. 2004// For example, if t represents int, ArrayOf(5, t) represents [5]int. 2005// 2006// If the resulting type would be larger than the available address space, 2007// ArrayOf panics. 2008func ArrayOf(count int, elem Type) Type { 2009 typ := elem.(*rtype) 2010 // call SliceOf here as it calls cacheGet/cachePut. 2011 // ArrayOf also calls cacheGet/cachePut and thus may modify the state of 2012 // the lookupCache mutex. 2013 slice := SliceOf(elem) 2014 2015 // Look in cache. 2016 ckey := cacheKey{Array, typ, nil, uintptr(count)} 2017 if array := cacheGet(ckey); array != nil { 2018 return array 2019 } 2020 2021 // Look in known types. 2022 s := "[" + strconv.Itoa(count) + "]" + *typ.string 2023 2024 // Make an array type. 2025 var iarray interface{} = [1]unsafe.Pointer{} 2026 prototype := *(**arrayType)(unsafe.Pointer(&iarray)) 2027 array := new(arrayType) 2028 *array = *prototype 2029 array.string = &s 2030 2031 // gccgo uses a different hash. 2032 // array.hash = fnv1(typ.hash, '[') 2033 // for n := uint32(count); n > 0; n >>= 8 { 2034 // array.hash = fnv1(array.hash, byte(n)) 2035 // } 2036 // array.hash = fnv1(array.hash, ']') 2037 array.hash = typ.hash + 1 + 13 2038 2039 array.elem = typ 2040 max := ^uintptr(0) / typ.size 2041 if uintptr(count) > max { 2042 panic("reflect.ArrayOf: array size would exceed virtual address space") 2043 } 2044 array.size = typ.size * uintptr(count) 2045 // if count > 0 && typ.ptrdata != 0 { 2046 // array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata 2047 // } 2048 array.align = typ.align 2049 array.fieldAlign = typ.fieldAlign 2050 array.uncommonType = nil 2051 array.ptrToThis = nil 2052 array.len = uintptr(count) 2053 array.slice = slice.(*rtype) 2054 2055 array.kind &^= kindNoPointers 2056 switch { 2057 case typ.kind&kindNoPointers != 0 || array.size == 0: 2058 // No pointers. 2059 array.kind |= kindNoPointers 2060 gc := [...]uintptr{array.size, _GC_END} 2061 array.gc = unsafe.Pointer(&gc[0]) 2062 2063 case count == 1: 2064 // In memory, 1-element array looks just like the element. 2065 array.kind |= typ.kind & kindGCProg 2066 array.gc = typ.gc 2067 2068 default: 2069 gc := []uintptr{array.size, _GC_ARRAY_START, 0, uintptr(count), typ.size} 2070 gc = appendGCProgram(gc, typ) 2071 gc = append(gc, _GC_ARRAY_NEXT, _GC_END) 2072 array.gc = unsafe.Pointer(&gc[0]) 2073 } 2074 2075 array.kind &^= kindDirectIface 2076 2077 array.hashfn = func(p unsafe.Pointer, size uintptr) uintptr { 2078 ret := uintptr(0) 2079 for i := 0; i < count; i++ { 2080 ret *= 33 2081 ret += typ.hashfn(p, typ.size) 2082 p = unsafe.Pointer(uintptr(p) + typ.size) 2083 } 2084 return ret 2085 } 2086 2087 array.equalfn = func(p1, p2 unsafe.Pointer, size uintptr) bool { 2088 for i := 0; i < count; i++ { 2089 if !typ.equalfn(p1, p2, typ.size) { 2090 return false 2091 } 2092 p1 = unsafe.Pointer(uintptr(p1) + typ.size) 2093 p2 = unsafe.Pointer(uintptr(p2) + typ.size) 2094 } 2095 return true 2096 } 2097 2098 return cachePut(ckey, &array.rtype) 2099} 2100 2101func appendVarint(x []byte, v uintptr) []byte { 2102 for ; v >= 0x80; v >>= 7 { 2103 x = append(x, byte(v|0x80)) 2104 } 2105 x = append(x, byte(v)) 2106 return x 2107} 2108 2109// toType converts from a *rtype to a Type that can be returned 2110// to the client of package reflect. In gc, the only concern is that 2111// a nil *rtype must be replaced by a nil Type, but in gccgo this 2112// function takes care of ensuring that multiple *rtype for the same 2113// type are coalesced into a single Type. 2114var canonicalType = make(map[string]Type) 2115 2116var canonicalTypeLock sync.RWMutex 2117 2118func canonicalize(t Type) Type { 2119 if t == nil { 2120 return nil 2121 } 2122 s := t.rawString() 2123 canonicalTypeLock.RLock() 2124 if r, ok := canonicalType[s]; ok { 2125 canonicalTypeLock.RUnlock() 2126 return r 2127 } 2128 canonicalTypeLock.RUnlock() 2129 canonicalTypeLock.Lock() 2130 if r, ok := canonicalType[s]; ok { 2131 canonicalTypeLock.Unlock() 2132 return r 2133 } 2134 canonicalType[s] = t 2135 canonicalTypeLock.Unlock() 2136 return t 2137} 2138 2139func toType(p *rtype) Type { 2140 if p == nil { 2141 return nil 2142 } 2143 return canonicalize(p) 2144} 2145 2146// ifaceIndir reports whether t is stored indirectly in an interface value. 2147func ifaceIndir(t *rtype) bool { 2148 return t.kind&kindDirectIface == 0 2149} 2150 2151// Layout matches runtime.BitVector (well enough). 2152type bitVector struct { 2153 n uint32 // number of bits 2154 data []byte 2155} 2156 2157// append a bit to the bitmap. 2158func (bv *bitVector) append(bit uint8) { 2159 if bv.n%8 == 0 { 2160 bv.data = append(bv.data, 0) 2161 } 2162 bv.data[bv.n/8] |= bit << (bv.n % 8) 2163 bv.n++ 2164} 2165 2166func addTypeBits(bv *bitVector, offset uintptr, t *rtype) { 2167 if t.kind&kindNoPointers != 0 { 2168 return 2169 } 2170 2171 switch Kind(t.kind & kindMask) { 2172 case Chan, Func, Map, Ptr, Slice, String, UnsafePointer: 2173 // 1 pointer at start of representation 2174 for bv.n < uint32(offset/uintptr(ptrSize)) { 2175 bv.append(0) 2176 } 2177 bv.append(1) 2178 2179 case Interface: 2180 // 2 pointers 2181 for bv.n < uint32(offset/uintptr(ptrSize)) { 2182 bv.append(0) 2183 } 2184 bv.append(1) 2185 bv.append(1) 2186 2187 case Array: 2188 // repeat inner type 2189 tt := (*arrayType)(unsafe.Pointer(t)) 2190 for i := 0; i < int(tt.len); i++ { 2191 addTypeBits(bv, offset+uintptr(i)*tt.elem.size, tt.elem) 2192 } 2193 2194 case Struct: 2195 // apply fields 2196 tt := (*structType)(unsafe.Pointer(t)) 2197 for i := range tt.fields { 2198 f := &tt.fields[i] 2199 addTypeBits(bv, offset+f.offset, f.typ) 2200 } 2201 } 2202} 2203