Source file
src/reflect/type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package reflect
17
18 import (
19 "internal/abi"
20 "internal/goarch"
21 "runtime"
22 "strconv"
23 "sync"
24 "unicode"
25 "unicode/utf8"
26 "unsafe"
27 )
28
29
30
31
32
33
34
35
36
37
38
39
40 type Type interface {
41
42
43
44
45 Align() int
46
47
48
49 FieldAlign() int
50
51
52
53
54
55
56
57
58
59
60
61
62 Method(int) Method
63
64
65
66
67
68
69
70
71
72 MethodByName(string) (Method, bool)
73
74
75
76
77
78
79 NumMethod() int
80
81
82
83 Name() string
84
85
86
87
88
89
90 PkgPath() string
91
92
93
94 Size() uintptr
95
96
97
98
99
100
101 String() string
102
103
104 Kind() Kind
105
106
107 Implements(u Type) bool
108
109
110 AssignableTo(u Type) bool
111
112
113
114
115
116 ConvertibleTo(u Type) bool
117
118
119
120
121
122 Comparable() bool
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 Bits() int
140
141
142
143 ChanDir() ChanDir
144
145
146
147
148
149
150
151
152
153
154
155
156
157 IsVariadic() bool
158
159
160
161 Elem() Type
162
163
164
165
166 Field(i int) StructField
167
168
169
170
171
172 FieldByIndex(index []int) StructField
173
174
175
176
177
178
179 FieldByName(name string) (StructField, bool)
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 FieldByNameFunc(match func(string) bool) (StructField, bool)
198
199
200
201
202 In(i int) Type
203
204
205
206 Key() Type
207
208
209
210 Len() int
211
212
213
214 NumField() int
215
216
217
218 NumIn() int
219
220
221
222 NumOut() int
223
224
225
226
227 Out(i int) Type
228
229
230
231 OverflowComplex(x complex128) bool
232
233
234
235 OverflowFloat(x float64) bool
236
237
238
239 OverflowInt(x int64) bool
240
241
242
243 OverflowUint(x uint64) bool
244
245
246 CanSeq() bool
247
248
249 CanSeq2() bool
250
251 common() *abi.Type
252 uncommon() *uncommonType
253 }
254
255
256
257
258
259
260
261
262
263
268
269
270
271 type Kind uint
272
273 const (
274 Invalid Kind = iota
275 Bool
276 Int
277 Int8
278 Int16
279 Int32
280 Int64
281 Uint
282 Uint8
283 Uint16
284 Uint32
285 Uint64
286 Uintptr
287 Float32
288 Float64
289 Complex64
290 Complex128
291 Array
292 Chan
293 Func
294 Interface
295 Map
296 Pointer
297 Slice
298 String
299 Struct
300 UnsafePointer
301 )
302
303
304 const Ptr = Pointer
305
306
307
308
309
310 type uncommonType = abi.UncommonType
311
312
313 type common struct {
314 abi.Type
315 }
316
317
318
319 type rtype struct {
320 t abi.Type
321 }
322
323 func (t *rtype) common() *abi.Type {
324 return &t.t
325 }
326
327 func (t *rtype) uncommon() *abi.UncommonType {
328 return t.t.Uncommon()
329 }
330
331 type aNameOff = abi.NameOff
332 type aTypeOff = abi.TypeOff
333 type aTextOff = abi.TextOff
334
335
336 type ChanDir int
337
338 const (
339 RecvDir ChanDir = 1 << iota
340 SendDir
341 BothDir = RecvDir | SendDir
342 )
343
344
345 type arrayType = abi.ArrayType
346
347
348 type chanType = abi.ChanType
349
350
351
352
353
354
355
356
357
358
359
360
361 type funcType = abi.FuncType
362
363
364 type interfaceType struct {
365 abi.InterfaceType
366 }
367
368 func (t *interfaceType) nameOff(off aNameOff) abi.Name {
369 return toRType(&t.Type).nameOff(off)
370 }
371
372 func nameOffFor(t *abi.Type, off aNameOff) abi.Name {
373 return toRType(t).nameOff(off)
374 }
375
376 func typeOffFor(t *abi.Type, off aTypeOff) *abi.Type {
377 return toRType(t).typeOff(off)
378 }
379
380 func (t *interfaceType) typeOff(off aTypeOff) *abi.Type {
381 return toRType(&t.Type).typeOff(off)
382 }
383
384 func (t *interfaceType) common() *abi.Type {
385 return &t.Type
386 }
387
388 func (t *interfaceType) uncommon() *abi.UncommonType {
389 return t.Uncommon()
390 }
391
392
393 type ptrType struct {
394 abi.PtrType
395 }
396
397
398 type sliceType struct {
399 abi.SliceType
400 }
401
402
403 type structField = abi.StructField
404
405
406 type structType struct {
407 abi.StructType
408 }
409
410 func pkgPath(n abi.Name) string {
411 if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
412 return ""
413 }
414 i, l := n.ReadVarint(1)
415 off := 1 + i + l
416 if n.HasTag() {
417 i2, l2 := n.ReadVarint(off)
418 off += i2 + l2
419 }
420 var nameOff int32
421
422
423 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
424 pkgPathName := abi.Name{Bytes: (*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
425 return pkgPathName.Name()
426 }
427
428 func newName(n, tag string, exported, embedded bool) abi.Name {
429 return abi.NewName(n, tag, exported, embedded)
430 }
431
432
436
437
438 type Method struct {
439
440 Name string
441
442
443
444
445
446
447 PkgPath string
448
449 Type Type
450 Func Value
451 Index int
452 }
453
454
455 func (m Method) IsExported() bool {
456 return m.PkgPath == ""
457 }
458
459
460 func (k Kind) String() string {
461 if uint(k) < uint(len(kindNames)) {
462 return kindNames[uint(k)]
463 }
464 return "kind" + strconv.Itoa(int(k))
465 }
466
467 var kindNames = []string{
468 Invalid: "invalid",
469 Bool: "bool",
470 Int: "int",
471 Int8: "int8",
472 Int16: "int16",
473 Int32: "int32",
474 Int64: "int64",
475 Uint: "uint",
476 Uint8: "uint8",
477 Uint16: "uint16",
478 Uint32: "uint32",
479 Uint64: "uint64",
480 Uintptr: "uintptr",
481 Float32: "float32",
482 Float64: "float64",
483 Complex64: "complex64",
484 Complex128: "complex128",
485 Array: "array",
486 Chan: "chan",
487 Func: "func",
488 Interface: "interface",
489 Map: "map",
490 Pointer: "ptr",
491 Slice: "slice",
492 String: "string",
493 Struct: "struct",
494 UnsafePointer: "unsafe.Pointer",
495 }
496
497
498
499
500
501
502 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
503
504
505
506
507
508
509 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
510
511
512
513
514
515
516 func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 func addReflectOff(ptr unsafe.Pointer) int32
533
534
535
536 func resolveReflectName(n abi.Name) aNameOff {
537 return aNameOff(addReflectOff(unsafe.Pointer(n.Bytes)))
538 }
539
540
541
542 func resolveReflectType(t *abi.Type) aTypeOff {
543 return aTypeOff(addReflectOff(unsafe.Pointer(t)))
544 }
545
546
547
548
549 func resolveReflectText(ptr unsafe.Pointer) aTextOff {
550 return aTextOff(addReflectOff(ptr))
551 }
552
553 func (t *rtype) nameOff(off aNameOff) abi.Name {
554 return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
555 }
556
557 func (t *rtype) typeOff(off aTypeOff) *abi.Type {
558 return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
559 }
560
561 func (t *rtype) textOff(off aTextOff) unsafe.Pointer {
562 return resolveTextOff(unsafe.Pointer(t), int32(off))
563 }
564
565 func textOffFor(t *abi.Type, off aTextOff) unsafe.Pointer {
566 return toRType(t).textOff(off)
567 }
568
569 func (t *rtype) String() string {
570 s := t.nameOff(t.t.Str).Name()
571 if t.t.TFlag&abi.TFlagExtraStar != 0 {
572 return s[1:]
573 }
574 return s
575 }
576
577 func (t *rtype) Size() uintptr { return t.t.Size() }
578
579 func (t *rtype) Bits() int {
580 if t == nil {
581 panic("reflect: Bits of nil Type")
582 }
583 k := t.Kind()
584 if k < Int || k > Complex128 {
585 panic("reflect: Bits of non-arithmetic Type " + t.String())
586 }
587 return int(t.t.Size_) * 8
588 }
589
590 func (t *rtype) Align() int { return t.t.Align() }
591
592 func (t *rtype) FieldAlign() int { return t.t.FieldAlign() }
593
594 func (t *rtype) Kind() Kind { return Kind(t.t.Kind()) }
595
596 func (t *rtype) exportedMethods() []abi.Method {
597 ut := t.uncommon()
598 if ut == nil {
599 return nil
600 }
601 return ut.ExportedMethods()
602 }
603
604 func (t *rtype) NumMethod() int {
605 if t.Kind() == Interface {
606 tt := (*interfaceType)(unsafe.Pointer(t))
607 return tt.NumMethod()
608 }
609 return len(t.exportedMethods())
610 }
611
612 func (t *rtype) Method(i int) (m Method) {
613 if t.Kind() == Interface {
614 tt := (*interfaceType)(unsafe.Pointer(t))
615 return tt.Method(i)
616 }
617 methods := t.exportedMethods()
618 if i < 0 || i >= len(methods) {
619 panic("reflect: Method index out of range")
620 }
621 p := methods[i]
622 pname := t.nameOff(p.Name)
623 m.Name = pname.Name()
624 fl := flag(Func)
625 mtyp := t.typeOff(p.Mtyp)
626 ft := (*funcType)(unsafe.Pointer(mtyp))
627 in := make([]Type, 0, 1+ft.NumIn())
628 in = append(in, t)
629 for _, arg := range ft.InSlice() {
630 in = append(in, toRType(arg))
631 }
632 out := make([]Type, 0, ft.NumOut())
633 for _, ret := range ft.OutSlice() {
634 out = append(out, toRType(ret))
635 }
636 mt := FuncOf(in, out, ft.IsVariadic())
637 m.Type = mt
638 tfn := t.textOff(p.Tfn)
639 fn := unsafe.Pointer(&tfn)
640 m.Func = Value{&mt.(*rtype).t, fn, fl}
641
642 m.Index = i
643 return m
644 }
645
646 func (t *rtype) MethodByName(name string) (m Method, ok bool) {
647 if t.Kind() == Interface {
648 tt := (*interfaceType)(unsafe.Pointer(t))
649 return tt.MethodByName(name)
650 }
651 ut := t.uncommon()
652 if ut == nil {
653 return Method{}, false
654 }
655
656 methods := ut.ExportedMethods()
657
658
659
660 i, j := 0, len(methods)
661 for i < j {
662 h := int(uint(i+j) >> 1)
663
664 if !(t.nameOff(methods[h].Name).Name() >= name) {
665 i = h + 1
666 } else {
667 j = h
668 }
669 }
670
671 if i < len(methods) && name == t.nameOff(methods[i].Name).Name() {
672 return t.Method(i), true
673 }
674
675 return Method{}, false
676 }
677
678 func (t *rtype) PkgPath() string {
679 if t.t.TFlag&abi.TFlagNamed == 0 {
680 return ""
681 }
682 ut := t.uncommon()
683 if ut == nil {
684 return ""
685 }
686 return t.nameOff(ut.PkgPath).Name()
687 }
688
689 func pkgPathFor(t *abi.Type) string {
690 return toRType(t).PkgPath()
691 }
692
693 func (t *rtype) Name() string {
694 if !t.t.HasName() {
695 return ""
696 }
697 s := t.String()
698 i := len(s) - 1
699 sqBrackets := 0
700 for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
701 switch s[i] {
702 case ']':
703 sqBrackets++
704 case '[':
705 sqBrackets--
706 }
707 i--
708 }
709 return s[i+1:]
710 }
711
712 func nameFor(t *abi.Type) string {
713 return toRType(t).Name()
714 }
715
716 func (t *rtype) ChanDir() ChanDir {
717 if t.Kind() != Chan {
718 panic("reflect: ChanDir of non-chan type " + t.String())
719 }
720 tt := (*abi.ChanType)(unsafe.Pointer(t))
721 return ChanDir(tt.Dir)
722 }
723
724 func toRType(t *abi.Type) *rtype {
725 return (*rtype)(unsafe.Pointer(t))
726 }
727
728 func elem(t *abi.Type) *abi.Type {
729 et := t.Elem()
730 if et != nil {
731 return et
732 }
733 panic("reflect: Elem of invalid type " + stringFor(t))
734 }
735
736 func (t *rtype) Elem() Type {
737 return toType(elem(t.common()))
738 }
739
740 func (t *rtype) Field(i int) StructField {
741 if t.Kind() != Struct {
742 panic("reflect: Field of non-struct type " + t.String())
743 }
744 tt := (*structType)(unsafe.Pointer(t))
745 return tt.Field(i)
746 }
747
748 func (t *rtype) FieldByIndex(index []int) StructField {
749 if t.Kind() != Struct {
750 panic("reflect: FieldByIndex of non-struct type " + t.String())
751 }
752 tt := (*structType)(unsafe.Pointer(t))
753 return tt.FieldByIndex(index)
754 }
755
756 func (t *rtype) FieldByName(name string) (StructField, bool) {
757 if t.Kind() != Struct {
758 panic("reflect: FieldByName of non-struct type " + t.String())
759 }
760 tt := (*structType)(unsafe.Pointer(t))
761 return tt.FieldByName(name)
762 }
763
764 func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
765 if t.Kind() != Struct {
766 panic("reflect: FieldByNameFunc of non-struct type " + t.String())
767 }
768 tt := (*structType)(unsafe.Pointer(t))
769 return tt.FieldByNameFunc(match)
770 }
771
772 func (t *rtype) Len() int {
773 if t.Kind() != Array {
774 panic("reflect: Len of non-array type " + t.String())
775 }
776 tt := (*arrayType)(unsafe.Pointer(t))
777 return int(tt.Len)
778 }
779
780 func (t *rtype) NumField() int {
781 if t.Kind() != Struct {
782 panic("reflect: NumField of non-struct type " + t.String())
783 }
784 tt := (*structType)(unsafe.Pointer(t))
785 return len(tt.Fields)
786 }
787
788 func (t *rtype) In(i int) Type {
789 if t.Kind() != Func {
790 panic("reflect: In of non-func type " + t.String())
791 }
792 tt := (*abi.FuncType)(unsafe.Pointer(t))
793 return toType(tt.InSlice()[i])
794 }
795
796 func (t *rtype) NumIn() int {
797 if t.Kind() != Func {
798 panic("reflect: NumIn of non-func type " + t.String())
799 }
800 tt := (*abi.FuncType)(unsafe.Pointer(t))
801 return tt.NumIn()
802 }
803
804 func (t *rtype) NumOut() int {
805 if t.Kind() != Func {
806 panic("reflect: NumOut of non-func type " + t.String())
807 }
808 tt := (*abi.FuncType)(unsafe.Pointer(t))
809 return tt.NumOut()
810 }
811
812 func (t *rtype) Out(i int) Type {
813 if t.Kind() != Func {
814 panic("reflect: Out of non-func type " + t.String())
815 }
816 tt := (*abi.FuncType)(unsafe.Pointer(t))
817 return toType(tt.OutSlice()[i])
818 }
819
820 func (t *rtype) IsVariadic() bool {
821 if t.Kind() != Func {
822 panic("reflect: IsVariadic of non-func type " + t.String())
823 }
824 tt := (*abi.FuncType)(unsafe.Pointer(t))
825 return tt.IsVariadic()
826 }
827
828 func (t *rtype) OverflowComplex(x complex128) bool {
829 k := t.Kind()
830 switch k {
831 case Complex64:
832 return overflowFloat32(real(x)) || overflowFloat32(imag(x))
833 case Complex128:
834 return false
835 }
836 panic("reflect: OverflowComplex of non-complex type " + t.String())
837 }
838
839 func (t *rtype) OverflowFloat(x float64) bool {
840 k := t.Kind()
841 switch k {
842 case Float32:
843 return overflowFloat32(x)
844 case Float64:
845 return false
846 }
847 panic("reflect: OverflowFloat of non-float type " + t.String())
848 }
849
850 func (t *rtype) OverflowInt(x int64) bool {
851 k := t.Kind()
852 switch k {
853 case Int, Int8, Int16, Int32, Int64:
854 bitSize := t.Size() * 8
855 trunc := (x << (64 - bitSize)) >> (64 - bitSize)
856 return x != trunc
857 }
858 panic("reflect: OverflowInt of non-int type " + t.String())
859 }
860
861 func (t *rtype) OverflowUint(x uint64) bool {
862 k := t.Kind()
863 switch k {
864 case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
865 bitSize := t.Size() * 8
866 trunc := (x << (64 - bitSize)) >> (64 - bitSize)
867 return x != trunc
868 }
869 panic("reflect: OverflowUint of non-uint type " + t.String())
870 }
871
872 func (t *rtype) CanSeq() bool {
873 switch t.Kind() {
874 case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Array, Slice, Chan, String, Map:
875 return true
876 case Func:
877 return canRangeFunc(&t.t)
878 case Pointer:
879 return t.Elem().Kind() == Array
880 }
881 return false
882 }
883
884 func canRangeFunc(t *abi.Type) bool {
885 if t.Kind() != abi.Func {
886 return false
887 }
888 f := t.FuncType()
889 if f.InCount != 1 || f.OutCount != 0 {
890 return false
891 }
892 y := f.In(0)
893 if y.Kind() != abi.Func {
894 return false
895 }
896 yield := y.FuncType()
897 return yield.InCount == 1 && yield.OutCount == 1 && yield.Out(0).Kind() == abi.Bool
898 }
899
900 func (t *rtype) CanSeq2() bool {
901 switch t.Kind() {
902 case Array, Slice, String, Map:
903 return true
904 case Func:
905 return canRangeFunc2(&t.t)
906 case Pointer:
907 return t.Elem().Kind() == Array
908 }
909 return false
910 }
911
912 func canRangeFunc2(t *abi.Type) bool {
913 if t.Kind() != abi.Func {
914 return false
915 }
916 f := t.FuncType()
917 if f.InCount != 1 || f.OutCount != 0 {
918 return false
919 }
920 y := f.In(0)
921 if y.Kind() != abi.Func {
922 return false
923 }
924 yield := y.FuncType()
925 return yield.InCount == 2 && yield.OutCount == 1 && yield.Out(0).Kind() == abi.Bool
926 }
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
947 return unsafe.Pointer(uintptr(p) + x)
948 }
949
950 func (d ChanDir) String() string {
951 switch d {
952 case SendDir:
953 return "chan<-"
954 case RecvDir:
955 return "<-chan"
956 case BothDir:
957 return "chan"
958 }
959 return "ChanDir" + strconv.Itoa(int(d))
960 }
961
962
963 func (t *interfaceType) Method(i int) (m Method) {
964 if i < 0 || i >= len(t.Methods) {
965 return
966 }
967 p := &t.Methods[i]
968 pname := t.nameOff(p.Name)
969 m.Name = pname.Name()
970 if !pname.IsExported() {
971 m.PkgPath = pkgPath(pname)
972 if m.PkgPath == "" {
973 m.PkgPath = t.PkgPath.Name()
974 }
975 }
976 m.Type = toType(t.typeOff(p.Typ))
977 m.Index = i
978 return
979 }
980
981
982 func (t *interfaceType) NumMethod() int { return len(t.Methods) }
983
984
985 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
986 if t == nil {
987 return
988 }
989 var p *abi.Imethod
990 for i := range t.Methods {
991 p = &t.Methods[i]
992 if t.nameOff(p.Name).Name() == name {
993 return t.Method(i), true
994 }
995 }
996 return
997 }
998
999
1000 type StructField struct {
1001
1002 Name string
1003
1004
1005
1006
1007 PkgPath string
1008
1009 Type Type
1010 Tag StructTag
1011 Offset uintptr
1012 Index []int
1013 Anonymous bool
1014 }
1015
1016
1017 func (f StructField) IsExported() bool {
1018 return f.PkgPath == ""
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029 type StructTag string
1030
1031
1032
1033
1034
1035
1036 func (tag StructTag) Get(key string) string {
1037 v, _ := tag.Lookup(key)
1038 return v
1039 }
1040
1041
1042
1043
1044
1045
1046
1047 func (tag StructTag) Lookup(key string) (value string, ok bool) {
1048
1049
1050
1051 for tag != "" {
1052
1053 i := 0
1054 for i < len(tag) && tag[i] == ' ' {
1055 i++
1056 }
1057 tag = tag[i:]
1058 if tag == "" {
1059 break
1060 }
1061
1062
1063
1064
1065
1066 i = 0
1067 for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
1068 i++
1069 }
1070 if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
1071 break
1072 }
1073 name := string(tag[:i])
1074 tag = tag[i+1:]
1075
1076
1077 i = 1
1078 for i < len(tag) && tag[i] != '"' {
1079 if tag[i] == '\\' {
1080 i++
1081 }
1082 i++
1083 }
1084 if i >= len(tag) {
1085 break
1086 }
1087 qvalue := string(tag[:i+1])
1088 tag = tag[i+1:]
1089
1090 if key == name {
1091 value, err := strconv.Unquote(qvalue)
1092 if err != nil {
1093 break
1094 }
1095 return value, true
1096 }
1097 }
1098 return "", false
1099 }
1100
1101
1102 func (t *structType) Field(i int) (f StructField) {
1103 if i < 0 || i >= len(t.Fields) {
1104 panic("reflect: Field index out of bounds")
1105 }
1106 p := &t.Fields[i]
1107 f.Type = toType(p.Typ)
1108 f.Name = p.Name.Name()
1109 f.Anonymous = p.Embedded()
1110 if !p.Name.IsExported() {
1111 f.PkgPath = t.PkgPath.Name()
1112 }
1113 if tag := p.Name.Tag(); tag != "" {
1114 f.Tag = StructTag(tag)
1115 }
1116 f.Offset = p.Offset
1117
1118
1119
1120 if i < 256 && runtime.GOOS != "js" && runtime.GOOS != "wasip1" {
1121 staticuint64s := getStaticuint64s()
1122 p := unsafe.Pointer(&(*staticuint64s)[i])
1123 if unsafe.Sizeof(int(0)) == 4 && goarch.BigEndian {
1124 p = unsafe.Add(p, 4)
1125 }
1126 f.Index = unsafe.Slice((*int)(p), 1)
1127 } else {
1128
1129
1130
1131
1132
1133
1134
1135 f.Index = []int{i}
1136 }
1137 return
1138 }
1139
1140
1141
1142
1143
1144
1145 func getStaticuint64s() *[256]uint64
1146
1147
1148
1149
1150
1151 func (t *structType) FieldByIndex(index []int) (f StructField) {
1152 f.Type = toType(&t.Type)
1153 for i, x := range index {
1154 if i > 0 {
1155 ft := f.Type
1156 if ft.Kind() == Pointer && ft.Elem().Kind() == Struct {
1157 ft = ft.Elem()
1158 }
1159 f.Type = ft
1160 }
1161 f = f.Type.Field(x)
1162 }
1163 return
1164 }
1165
1166
1167 type fieldScan struct {
1168 typ *structType
1169 index []int
1170 }
1171
1172
1173
1174 func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
1175
1176
1177
1178
1179
1180
1181
1182
1183 current := []fieldScan{}
1184 next := []fieldScan{{typ: t}}
1185
1186
1187
1188
1189
1190
1191
1192 var nextCount map[*structType]int
1193
1194
1195
1196
1197
1198
1199 visited := map[*structType]bool{}
1200
1201 for len(next) > 0 {
1202 current, next = next, current[:0]
1203 count := nextCount
1204 nextCount = nil
1205
1206
1207
1208
1209
1210 for _, scan := range current {
1211 t := scan.typ
1212 if visited[t] {
1213
1214
1215
1216 continue
1217 }
1218 visited[t] = true
1219 for i := range t.Fields {
1220 f := &t.Fields[i]
1221
1222 fname := f.Name.Name()
1223 var ntyp *abi.Type
1224 if f.Embedded() {
1225
1226 ntyp = f.Typ
1227 if ntyp.Kind() == abi.Pointer {
1228 ntyp = ntyp.Elem()
1229 }
1230 }
1231
1232
1233 if match(fname) {
1234
1235 if count[t] > 1 || ok {
1236
1237 return StructField{}, false
1238 }
1239 result = t.Field(i)
1240 result.Index = nil
1241 result.Index = append(result.Index, scan.index...)
1242 result.Index = append(result.Index, i)
1243 ok = true
1244 continue
1245 }
1246
1247
1248
1249
1250 if ok || ntyp == nil || ntyp.Kind() != abi.Struct {
1251 continue
1252 }
1253 styp := (*structType)(unsafe.Pointer(ntyp))
1254 if nextCount[styp] > 0 {
1255 nextCount[styp] = 2
1256 continue
1257 }
1258 if nextCount == nil {
1259 nextCount = map[*structType]int{}
1260 }
1261 nextCount[styp] = 1
1262 if count[t] > 1 {
1263 nextCount[styp] = 2
1264 }
1265 var index []int
1266 index = append(index, scan.index...)
1267 index = append(index, i)
1268 next = append(next, fieldScan{styp, index})
1269 }
1270 }
1271 if ok {
1272 break
1273 }
1274 }
1275 return
1276 }
1277
1278
1279
1280 func (t *structType) FieldByName(name string) (f StructField, present bool) {
1281
1282 hasEmbeds := false
1283 if name != "" {
1284 for i := range t.Fields {
1285 tf := &t.Fields[i]
1286 if tf.Name.Name() == name {
1287 return t.Field(i), true
1288 }
1289 if tf.Embedded() {
1290 hasEmbeds = true
1291 }
1292 }
1293 }
1294 if !hasEmbeds {
1295 return
1296 }
1297 return t.FieldByNameFunc(func(s string) bool { return s == name })
1298 }
1299
1300
1301
1302 func TypeOf(i any) Type {
1303 return toType(abi.TypeOf(i))
1304 }
1305
1306
1307 func rtypeOf(i any) *abi.Type {
1308 return abi.TypeOf(i)
1309 }
1310
1311
1312 var ptrMap sync.Map
1313
1314
1315
1316
1317
1318
1319
1320
1321 func PtrTo(t Type) Type { return PointerTo(t) }
1322
1323
1324
1325 func PointerTo(t Type) Type {
1326 return toRType(t.(*rtype).ptrTo())
1327 }
1328
1329 func (t *rtype) ptrTo() *abi.Type {
1330 at := &t.t
1331 if at.PtrToThis != 0 {
1332 return t.typeOff(at.PtrToThis)
1333 }
1334
1335
1336 if pi, ok := ptrMap.Load(t); ok {
1337 return &pi.(*ptrType).Type
1338 }
1339
1340
1341 s := "*" + t.String()
1342 for _, tt := range typesByString(s) {
1343 p := (*ptrType)(unsafe.Pointer(tt))
1344 if p.Elem != &t.t {
1345 continue
1346 }
1347 pi, _ := ptrMap.LoadOrStore(t, p)
1348 return &pi.(*ptrType).Type
1349 }
1350
1351
1352
1353 var iptr any = (*unsafe.Pointer)(nil)
1354 prototype := *(**ptrType)(unsafe.Pointer(&iptr))
1355 pp := *prototype
1356
1357 pp.Str = resolveReflectName(newName(s, "", false, false))
1358 pp.PtrToThis = 0
1359
1360
1361
1362
1363
1364
1365 pp.Hash = fnv1(t.t.Hash, '*')
1366
1367 pp.Elem = at
1368
1369 pi, _ := ptrMap.LoadOrStore(t, &pp)
1370 return &pi.(*ptrType).Type
1371 }
1372
1373 func ptrTo(t *abi.Type) *abi.Type {
1374 return toRType(t).ptrTo()
1375 }
1376
1377
1378 func fnv1(x uint32, list ...byte) uint32 {
1379 for _, b := range list {
1380 x = x*16777619 ^ uint32(b)
1381 }
1382 return x
1383 }
1384
1385 func (t *rtype) Implements(u Type) bool {
1386 if u == nil {
1387 panic("reflect: nil type passed to Type.Implements")
1388 }
1389 if u.Kind() != Interface {
1390 panic("reflect: non-interface type passed to Type.Implements")
1391 }
1392 return implements(u.common(), t.common())
1393 }
1394
1395 func (t *rtype) AssignableTo(u Type) bool {
1396 if u == nil {
1397 panic("reflect: nil type passed to Type.AssignableTo")
1398 }
1399 uu := u.common()
1400 return directlyAssignable(uu, t.common()) || implements(uu, t.common())
1401 }
1402
1403 func (t *rtype) ConvertibleTo(u Type) bool {
1404 if u == nil {
1405 panic("reflect: nil type passed to Type.ConvertibleTo")
1406 }
1407 return convertOp(u.common(), t.common()) != nil
1408 }
1409
1410 func (t *rtype) Comparable() bool {
1411 return t.t.Equal != nil
1412 }
1413
1414
1415 func implements(T, V *abi.Type) bool {
1416 if T.Kind() != abi.Interface {
1417 return false
1418 }
1419 t := (*interfaceType)(unsafe.Pointer(T))
1420 if len(t.Methods) == 0 {
1421 return true
1422 }
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436 if V.Kind() == abi.Interface {
1437 v := (*interfaceType)(unsafe.Pointer(V))
1438 i := 0
1439 for j := 0; j < len(v.Methods); j++ {
1440 tm := &t.Methods[i]
1441 tmName := t.nameOff(tm.Name)
1442 vm := &v.Methods[j]
1443 vmName := nameOffFor(V, vm.Name)
1444 if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Typ) == t.typeOff(tm.Typ) {
1445 if !tmName.IsExported() {
1446 tmPkgPath := pkgPath(tmName)
1447 if tmPkgPath == "" {
1448 tmPkgPath = t.PkgPath.Name()
1449 }
1450 vmPkgPath := pkgPath(vmName)
1451 if vmPkgPath == "" {
1452 vmPkgPath = v.PkgPath.Name()
1453 }
1454 if tmPkgPath != vmPkgPath {
1455 continue
1456 }
1457 }
1458 if i++; i >= len(t.Methods) {
1459 return true
1460 }
1461 }
1462 }
1463 return false
1464 }
1465
1466 v := V.Uncommon()
1467 if v == nil {
1468 return false
1469 }
1470 i := 0
1471 vmethods := v.Methods()
1472 for j := 0; j < int(v.Mcount); j++ {
1473 tm := &t.Methods[i]
1474 tmName := t.nameOff(tm.Name)
1475 vm := vmethods[j]
1476 vmName := nameOffFor(V, vm.Name)
1477 if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Mtyp) == t.typeOff(tm.Typ) {
1478 if !tmName.IsExported() {
1479 tmPkgPath := pkgPath(tmName)
1480 if tmPkgPath == "" {
1481 tmPkgPath = t.PkgPath.Name()
1482 }
1483 vmPkgPath := pkgPath(vmName)
1484 if vmPkgPath == "" {
1485 vmPkgPath = nameOffFor(V, v.PkgPath).Name()
1486 }
1487 if tmPkgPath != vmPkgPath {
1488 continue
1489 }
1490 }
1491 if i++; i >= len(t.Methods) {
1492 return true
1493 }
1494 }
1495 }
1496 return false
1497 }
1498
1499
1500
1501
1502
1503 func specialChannelAssignability(T, V *abi.Type) bool {
1504
1505
1506
1507
1508 return V.ChanDir() == abi.BothDir && (nameFor(T) == "" || nameFor(V) == "") && haveIdenticalType(T.Elem(), V.Elem(), true)
1509 }
1510
1511
1512
1513
1514
1515
1516 func directlyAssignable(T, V *abi.Type) bool {
1517
1518 if T == V {
1519 return true
1520 }
1521
1522
1523
1524 if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
1525 return false
1526 }
1527
1528 if T.Kind() == abi.Chan && specialChannelAssignability(T, V) {
1529 return true
1530 }
1531
1532
1533 return haveIdenticalUnderlyingType(T, V, true)
1534 }
1535
1536 func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
1537 if cmpTags {
1538 return T == V
1539 }
1540
1541 if nameFor(T) != nameFor(V) || T.Kind() != V.Kind() || pkgPathFor(T) != pkgPathFor(V) {
1542 return false
1543 }
1544
1545 return haveIdenticalUnderlyingType(T, V, false)
1546 }
1547
1548 func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
1549 if T == V {
1550 return true
1551 }
1552
1553 kind := Kind(T.Kind())
1554 if kind != Kind(V.Kind()) {
1555 return false
1556 }
1557
1558
1559
1560 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
1561 return true
1562 }
1563
1564
1565 switch kind {
1566 case Array:
1567 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1568
1569 case Chan:
1570 return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1571
1572 case Func:
1573 t := (*funcType)(unsafe.Pointer(T))
1574 v := (*funcType)(unsafe.Pointer(V))
1575 if t.OutCount != v.OutCount || t.InCount != v.InCount {
1576 return false
1577 }
1578 for i := 0; i < t.NumIn(); i++ {
1579 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
1580 return false
1581 }
1582 }
1583 for i := 0; i < t.NumOut(); i++ {
1584 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
1585 return false
1586 }
1587 }
1588 return true
1589
1590 case Interface:
1591 t := (*interfaceType)(unsafe.Pointer(T))
1592 v := (*interfaceType)(unsafe.Pointer(V))
1593 if len(t.Methods) == 0 && len(v.Methods) == 0 {
1594 return true
1595 }
1596
1597
1598 return false
1599
1600 case Map:
1601 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1602
1603 case Pointer, Slice:
1604 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1605
1606 case Struct:
1607 t := (*structType)(unsafe.Pointer(T))
1608 v := (*structType)(unsafe.Pointer(V))
1609 if len(t.Fields) != len(v.Fields) {
1610 return false
1611 }
1612 if t.PkgPath.Name() != v.PkgPath.Name() {
1613 return false
1614 }
1615 for i := range t.Fields {
1616 tf := &t.Fields[i]
1617 vf := &v.Fields[i]
1618 if tf.Name.Name() != vf.Name.Name() {
1619 return false
1620 }
1621 if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
1622 return false
1623 }
1624 if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
1625 return false
1626 }
1627 if tf.Offset != vf.Offset {
1628 return false
1629 }
1630 if tf.Embedded() != vf.Embedded() {
1631 return false
1632 }
1633 }
1634 return true
1635 }
1636
1637 return false
1638 }
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659 func typelinks() (sections []unsafe.Pointer, offset [][]int32)
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670 func rtypeOff(section unsafe.Pointer, off int32) *abi.Type {
1671 return (*abi.Type)(add(section, uintptr(off), "sizeof(rtype) > 0"))
1672 }
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689 func typesByString(s string) []*abi.Type {
1690 sections, offset := typelinks()
1691 var ret []*abi.Type
1692
1693 for offsI, offs := range offset {
1694 section := sections[offsI]
1695
1696
1697
1698 i, j := 0, len(offs)
1699 for i < j {
1700 h := int(uint(i+j) >> 1)
1701
1702 if !(stringFor(rtypeOff(section, offs[h])) >= s) {
1703 i = h + 1
1704 } else {
1705 j = h
1706 }
1707 }
1708
1709
1710
1711
1712
1713 for j := i; j < len(offs); j++ {
1714 typ := rtypeOff(section, offs[j])
1715 if stringFor(typ) != s {
1716 break
1717 }
1718 ret = append(ret, typ)
1719 }
1720 }
1721 return ret
1722 }
1723
1724
1725 var lookupCache sync.Map
1726
1727
1728
1729
1730 type cacheKey struct {
1731 kind Kind
1732 t1 *abi.Type
1733 t2 *abi.Type
1734 extra uintptr
1735 }
1736
1737
1738
1739
1740 var funcLookupCache struct {
1741 sync.Mutex
1742
1743
1744
1745 m sync.Map
1746 }
1747
1748
1749
1750
1751
1752
1753 func ChanOf(dir ChanDir, t Type) Type {
1754 typ := t.common()
1755
1756
1757 ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
1758 if ch, ok := lookupCache.Load(ckey); ok {
1759 return ch.(*rtype)
1760 }
1761
1762
1763 if typ.Size_ >= 1<<16 {
1764 panic("reflect.ChanOf: element size too large")
1765 }
1766
1767
1768 var s string
1769 switch dir {
1770 default:
1771 panic("reflect.ChanOf: invalid dir")
1772 case SendDir:
1773 s = "chan<- " + stringFor(typ)
1774 case RecvDir:
1775 s = "<-chan " + stringFor(typ)
1776 case BothDir:
1777 typeStr := stringFor(typ)
1778 if typeStr[0] == '<' {
1779
1780
1781
1782
1783 s = "chan (" + typeStr + ")"
1784 } else {
1785 s = "chan " + typeStr
1786 }
1787 }
1788 for _, tt := range typesByString(s) {
1789 ch := (*chanType)(unsafe.Pointer(tt))
1790 if ch.Elem == typ && ch.Dir == abi.ChanDir(dir) {
1791 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
1792 return ti.(Type)
1793 }
1794 }
1795
1796
1797 var ichan any = (chan unsafe.Pointer)(nil)
1798 prototype := *(**chanType)(unsafe.Pointer(&ichan))
1799 ch := *prototype
1800 ch.TFlag = abi.TFlagRegularMemory
1801 ch.Dir = abi.ChanDir(dir)
1802 ch.Str = resolveReflectName(newName(s, "", false, false))
1803 ch.Hash = fnv1(typ.Hash, 'c', byte(dir))
1804 ch.Elem = typ
1805
1806 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&ch.Type))
1807 return ti.(Type)
1808 }
1809
1810 var funcTypes []Type
1811 var funcTypesMutex sync.Mutex
1812
1813 func initFuncTypes(n int) Type {
1814 funcTypesMutex.Lock()
1815 defer funcTypesMutex.Unlock()
1816 if n >= len(funcTypes) {
1817 newFuncTypes := make([]Type, n+1)
1818 copy(newFuncTypes, funcTypes)
1819 funcTypes = newFuncTypes
1820 }
1821 if funcTypes[n] != nil {
1822 return funcTypes[n]
1823 }
1824
1825 funcTypes[n] = StructOf([]StructField{
1826 {
1827 Name: "FuncType",
1828 Type: TypeOf(funcType{}),
1829 },
1830 {
1831 Name: "Args",
1832 Type: ArrayOf(n, TypeOf(&rtype{})),
1833 },
1834 })
1835 return funcTypes[n]
1836 }
1837
1838
1839
1840
1841
1842
1843
1844
1845 func FuncOf(in, out []Type, variadic bool) Type {
1846 if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) {
1847 panic("reflect.FuncOf: last arg of variadic func must be slice")
1848 }
1849
1850
1851 var ifunc any = (func())(nil)
1852 prototype := *(**funcType)(unsafe.Pointer(&ifunc))
1853 n := len(in) + len(out)
1854
1855 if n > 128 {
1856 panic("reflect.FuncOf: too many arguments")
1857 }
1858
1859 o := New(initFuncTypes(n)).Elem()
1860 ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
1861 args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
1862 *ft = *prototype
1863
1864
1865 var hash uint32
1866 for _, in := range in {
1867 t := in.(*rtype)
1868 args = append(args, t)
1869 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1870 }
1871 if variadic {
1872 hash = fnv1(hash, 'v')
1873 }
1874 hash = fnv1(hash, '.')
1875 for _, out := range out {
1876 t := out.(*rtype)
1877 args = append(args, t)
1878 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1879 }
1880
1881 ft.TFlag = 0
1882 ft.Hash = hash
1883 ft.InCount = uint16(len(in))
1884 ft.OutCount = uint16(len(out))
1885 if variadic {
1886 ft.OutCount |= 1 << 15
1887 }
1888
1889
1890 if ts, ok := funcLookupCache.m.Load(hash); ok {
1891 for _, t := range ts.([]*abi.Type) {
1892 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1893 return toRType(t)
1894 }
1895 }
1896 }
1897
1898
1899 funcLookupCache.Lock()
1900 defer funcLookupCache.Unlock()
1901 if ts, ok := funcLookupCache.m.Load(hash); ok {
1902 for _, t := range ts.([]*abi.Type) {
1903 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1904 return toRType(t)
1905 }
1906 }
1907 }
1908
1909 addToCache := func(tt *abi.Type) Type {
1910 var rts []*abi.Type
1911 if rti, ok := funcLookupCache.m.Load(hash); ok {
1912 rts = rti.([]*abi.Type)
1913 }
1914 funcLookupCache.m.Store(hash, append(rts, tt))
1915 return toType(tt)
1916 }
1917
1918
1919 str := funcStr(ft)
1920 for _, tt := range typesByString(str) {
1921 if haveIdenticalUnderlyingType(&ft.Type, tt, true) {
1922 return addToCache(tt)
1923 }
1924 }
1925
1926
1927 ft.Str = resolveReflectName(newName(str, "", false, false))
1928 ft.PtrToThis = 0
1929 return addToCache(&ft.Type)
1930 }
1931 func stringFor(t *abi.Type) string {
1932 return toRType(t).String()
1933 }
1934
1935
1936 func funcStr(ft *funcType) string {
1937 repr := make([]byte, 0, 64)
1938 repr = append(repr, "func("...)
1939 for i, t := range ft.InSlice() {
1940 if i > 0 {
1941 repr = append(repr, ", "...)
1942 }
1943 if ft.IsVariadic() && i == int(ft.InCount)-1 {
1944 repr = append(repr, "..."...)
1945 repr = append(repr, stringFor((*sliceType)(unsafe.Pointer(t)).Elem)...)
1946 } else {
1947 repr = append(repr, stringFor(t)...)
1948 }
1949 }
1950 repr = append(repr, ')')
1951 out := ft.OutSlice()
1952 if len(out) == 1 {
1953 repr = append(repr, ' ')
1954 } else if len(out) > 1 {
1955 repr = append(repr, " ("...)
1956 }
1957 for i, t := range out {
1958 if i > 0 {
1959 repr = append(repr, ", "...)
1960 }
1961 repr = append(repr, stringFor(t)...)
1962 }
1963 if len(out) > 1 {
1964 repr = append(repr, ')')
1965 }
1966 return string(repr)
1967 }
1968
1969
1970
1971 func isReflexive(t *abi.Type) bool {
1972 switch Kind(t.Kind()) {
1973 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, String, UnsafePointer:
1974 return true
1975 case Float32, Float64, Complex64, Complex128, Interface:
1976 return false
1977 case Array:
1978 tt := (*arrayType)(unsafe.Pointer(t))
1979 return isReflexive(tt.Elem)
1980 case Struct:
1981 tt := (*structType)(unsafe.Pointer(t))
1982 for _, f := range tt.Fields {
1983 if !isReflexive(f.Typ) {
1984 return false
1985 }
1986 }
1987 return true
1988 default:
1989
1990 panic("isReflexive called on non-key type " + stringFor(t))
1991 }
1992 }
1993
1994
1995 func needKeyUpdate(t *abi.Type) bool {
1996 switch Kind(t.Kind()) {
1997 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, UnsafePointer:
1998 return false
1999 case Float32, Float64, Complex64, Complex128, Interface, String:
2000
2001
2002
2003 return true
2004 case Array:
2005 tt := (*arrayType)(unsafe.Pointer(t))
2006 return needKeyUpdate(tt.Elem)
2007 case Struct:
2008 tt := (*structType)(unsafe.Pointer(t))
2009 for _, f := range tt.Fields {
2010 if needKeyUpdate(f.Typ) {
2011 return true
2012 }
2013 }
2014 return false
2015 default:
2016
2017 panic("needKeyUpdate called on non-key type " + stringFor(t))
2018 }
2019 }
2020
2021
2022 func hashMightPanic(t *abi.Type) bool {
2023 switch Kind(t.Kind()) {
2024 case Interface:
2025 return true
2026 case Array:
2027 tt := (*arrayType)(unsafe.Pointer(t))
2028 return hashMightPanic(tt.Elem)
2029 case Struct:
2030 tt := (*structType)(unsafe.Pointer(t))
2031 for _, f := range tt.Fields {
2032 if hashMightPanic(f.Typ) {
2033 return true
2034 }
2035 }
2036 return false
2037 default:
2038 return false
2039 }
2040 }
2041
2042
2043
2044 func emitGCMask(out []byte, base uintptr, typ *abi.Type, n uintptr) {
2045 ptrs := typ.PtrBytes / goarch.PtrSize
2046 words := typ.Size_ / goarch.PtrSize
2047 mask := typ.GcSlice(0, (ptrs+7)/8)
2048 for j := uintptr(0); j < ptrs; j++ {
2049 if (mask[j/8]>>(j%8))&1 != 0 {
2050 for i := uintptr(0); i < n; i++ {
2051 k := base + i*words + j
2052 out[k/8] |= 1 << (k % 8)
2053 }
2054 }
2055 }
2056 }
2057
2058
2059
2060 func SliceOf(t Type) Type {
2061 typ := t.common()
2062
2063
2064 ckey := cacheKey{Slice, typ, nil, 0}
2065 if slice, ok := lookupCache.Load(ckey); ok {
2066 return slice.(Type)
2067 }
2068
2069
2070 s := "[]" + stringFor(typ)
2071 for _, tt := range typesByString(s) {
2072 slice := (*sliceType)(unsafe.Pointer(tt))
2073 if slice.Elem == typ {
2074 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2075 return ti.(Type)
2076 }
2077 }
2078
2079
2080 var islice any = ([]unsafe.Pointer)(nil)
2081 prototype := *(**sliceType)(unsafe.Pointer(&islice))
2082 slice := *prototype
2083 slice.TFlag = 0
2084 slice.Str = resolveReflectName(newName(s, "", false, false))
2085 slice.Hash = fnv1(typ.Hash, '[')
2086 slice.Elem = typ
2087 slice.PtrToThis = 0
2088
2089 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&slice.Type))
2090 return ti.(Type)
2091 }
2092
2093
2094
2095
2096 var structLookupCache struct {
2097 sync.Mutex
2098
2099
2100
2101 m sync.Map
2102 }
2103
2104 type structTypeUncommon struct {
2105 structType
2106 u uncommonType
2107 }
2108
2109
2110 func isLetter(ch rune) bool {
2111 return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
2112 }
2113
2114
2115
2116
2117
2118
2119
2120 func isValidFieldName(fieldName string) bool {
2121 for i, c := range fieldName {
2122 if i == 0 && !isLetter(c) {
2123 return false
2124 }
2125
2126 if !(isLetter(c) || unicode.IsDigit(c)) {
2127 return false
2128 }
2129 }
2130
2131 return len(fieldName) > 0
2132 }
2133
2134
2135 func isRegularMemory(t Type) bool {
2136 switch t.Kind() {
2137 case Array:
2138 elem := t.Elem()
2139 if isRegularMemory(elem) {
2140 return true
2141 }
2142 return elem.Comparable() && t.Len() == 0
2143 case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Chan, Pointer, Bool, UnsafePointer:
2144 return true
2145 case Struct:
2146 num := t.NumField()
2147 switch num {
2148 case 0:
2149 return true
2150 case 1:
2151 field := t.Field(0)
2152 if field.Name == "_" {
2153 return false
2154 }
2155 return isRegularMemory(field.Type)
2156 default:
2157 for i := range num {
2158 field := t.Field(i)
2159 if field.Name == "_" || !isRegularMemory(field.Type) || isPaddedField(t, i) {
2160 return false
2161 }
2162 }
2163 return true
2164 }
2165 }
2166 return false
2167 }
2168
2169
2170
2171 func isPaddedField(t Type, i int) bool {
2172 field := t.Field(i)
2173 if i+1 < t.NumField() {
2174 return field.Offset+field.Type.Size() != t.Field(i+1).Offset
2175 }
2176 return field.Offset+field.Type.Size() != t.Size()
2177 }
2178
2179
2180
2181
2182
2183
2184
2185 func StructOf(fields []StructField) Type {
2186 var (
2187 hash = fnv1(0, []byte("struct {")...)
2188 size uintptr
2189 typalign uint8
2190 comparable = true
2191 methods []abi.Method
2192
2193 fs = make([]structField, len(fields))
2194 repr = make([]byte, 0, 64)
2195 fset = map[string]struct{}{}
2196 )
2197
2198 lastzero := uintptr(0)
2199 repr = append(repr, "struct {"...)
2200 pkgpath := ""
2201 for i, field := range fields {
2202 if field.Name == "" {
2203 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
2204 }
2205 if !isValidFieldName(field.Name) {
2206 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
2207 }
2208 if field.Type == nil {
2209 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
2210 }
2211 f, fpkgpath := runtimeStructField(field)
2212 ft := f.Typ
2213 if fpkgpath != "" {
2214 if pkgpath == "" {
2215 pkgpath = fpkgpath
2216 } else if pkgpath != fpkgpath {
2217 panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
2218 }
2219 }
2220
2221
2222 name := f.Name.Name()
2223 hash = fnv1(hash, []byte(name)...)
2224 if !f.Embedded() {
2225 repr = append(repr, (" " + name)...)
2226 } else {
2227
2228 if f.Typ.Kind() == abi.Pointer {
2229
2230 elem := ft.Elem()
2231 if k := elem.Kind(); k == abi.Pointer || k == abi.Interface {
2232 panic("reflect.StructOf: illegal embedded field type " + stringFor(ft))
2233 }
2234 }
2235
2236 switch Kind(f.Typ.Kind()) {
2237 case Interface:
2238 ift := (*interfaceType)(unsafe.Pointer(ft))
2239 for _, m := range ift.Methods {
2240 if pkgPath(ift.nameOff(m.Name)) != "" {
2241
2242 panic("reflect: embedded interface with unexported method(s) not implemented")
2243 }
2244
2245 fnStub := resolveReflectText(unsafe.Pointer(abi.FuncPCABIInternal(embeddedIfaceMethStub)))
2246 methods = append(methods, abi.Method{
2247 Name: resolveReflectName(ift.nameOff(m.Name)),
2248 Mtyp: resolveReflectType(ift.typeOff(m.Typ)),
2249 Ifn: fnStub,
2250 Tfn: fnStub,
2251 })
2252 }
2253 case Pointer:
2254 ptr := (*ptrType)(unsafe.Pointer(ft))
2255 if unt := ptr.Uncommon(); unt != nil {
2256 if i > 0 && unt.Mcount > 0 {
2257
2258 panic("reflect: embedded type with methods not implemented if type is not first field")
2259 }
2260 if len(fields) > 1 {
2261 panic("reflect: embedded type with methods not implemented if there is more than one field")
2262 }
2263 for _, m := range unt.Methods() {
2264 mname := nameOffFor(ft, m.Name)
2265 if pkgPath(mname) != "" {
2266
2267
2268 panic("reflect: embedded interface with unexported method(s) not implemented")
2269 }
2270 methods = append(methods, abi.Method{
2271 Name: resolveReflectName(mname),
2272 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2273 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2274 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2275 })
2276 }
2277 }
2278 if unt := ptr.Elem.Uncommon(); unt != nil {
2279 for _, m := range unt.Methods() {
2280 mname := nameOffFor(ft, m.Name)
2281 if pkgPath(mname) != "" {
2282
2283
2284 panic("reflect: embedded interface with unexported method(s) not implemented")
2285 }
2286 methods = append(methods, abi.Method{
2287 Name: resolveReflectName(mname),
2288 Mtyp: resolveReflectType(typeOffFor(ptr.Elem, m.Mtyp)),
2289 Ifn: resolveReflectText(textOffFor(ptr.Elem, m.Ifn)),
2290 Tfn: resolveReflectText(textOffFor(ptr.Elem, m.Tfn)),
2291 })
2292 }
2293 }
2294 default:
2295 if unt := ft.Uncommon(); unt != nil {
2296 if i > 0 && unt.Mcount > 0 {
2297
2298 panic("reflect: embedded type with methods not implemented if type is not first field")
2299 }
2300 if len(fields) > 1 && ft.Kind_&abi.KindDirectIface != 0 {
2301 panic("reflect: embedded type with methods not implemented for non-pointer type")
2302 }
2303 for _, m := range unt.Methods() {
2304 mname := nameOffFor(ft, m.Name)
2305 if pkgPath(mname) != "" {
2306
2307
2308 panic("reflect: embedded interface with unexported method(s) not implemented")
2309 }
2310 methods = append(methods, abi.Method{
2311 Name: resolveReflectName(mname),
2312 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2313 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2314 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2315 })
2316
2317 }
2318 }
2319 }
2320 }
2321 if _, dup := fset[name]; dup && name != "_" {
2322 panic("reflect.StructOf: duplicate field " + name)
2323 }
2324 fset[name] = struct{}{}
2325
2326 hash = fnv1(hash, byte(ft.Hash>>24), byte(ft.Hash>>16), byte(ft.Hash>>8), byte(ft.Hash))
2327
2328 repr = append(repr, (" " + stringFor(ft))...)
2329 if f.Name.HasTag() {
2330 hash = fnv1(hash, []byte(f.Name.Tag())...)
2331 repr = append(repr, (" " + strconv.Quote(f.Name.Tag()))...)
2332 }
2333 if i < len(fields)-1 {
2334 repr = append(repr, ';')
2335 }
2336
2337 comparable = comparable && (ft.Equal != nil)
2338
2339 offset := align(size, uintptr(ft.Align_))
2340 if offset < size {
2341 panic("reflect.StructOf: struct size would exceed virtual address space")
2342 }
2343 if ft.Align_ > typalign {
2344 typalign = ft.Align_
2345 }
2346 size = offset + ft.Size_
2347 if size < offset {
2348 panic("reflect.StructOf: struct size would exceed virtual address space")
2349 }
2350 f.Offset = offset
2351
2352 if ft.Size_ == 0 {
2353 lastzero = size
2354 }
2355
2356 fs[i] = f
2357 }
2358
2359 if size > 0 && lastzero == size {
2360
2361
2362
2363
2364
2365 size++
2366 if size == 0 {
2367 panic("reflect.StructOf: struct size would exceed virtual address space")
2368 }
2369 }
2370
2371 var typ *structType
2372 var ut *uncommonType
2373
2374 if len(methods) == 0 {
2375 t := new(structTypeUncommon)
2376 typ = &t.structType
2377 ut = &t.u
2378 } else {
2379
2380
2381
2382
2383
2384 tt := New(StructOf([]StructField{
2385 {Name: "S", Type: TypeOf(structType{})},
2386 {Name: "U", Type: TypeOf(uncommonType{})},
2387 {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
2388 }))
2389
2390 typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer())
2391 ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer())
2392
2393 copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]abi.Method), methods)
2394 }
2395
2396
2397
2398
2399 ut.Mcount = uint16(len(methods))
2400 ut.Xcount = ut.Mcount
2401 ut.Moff = uint32(unsafe.Sizeof(uncommonType{}))
2402
2403 if len(fs) > 0 {
2404 repr = append(repr, ' ')
2405 }
2406 repr = append(repr, '}')
2407 hash = fnv1(hash, '}')
2408 str := string(repr)
2409
2410
2411 s := align(size, uintptr(typalign))
2412 if s < size {
2413 panic("reflect.StructOf: struct size would exceed virtual address space")
2414 }
2415 size = s
2416
2417
2418 var istruct any = struct{}{}
2419 prototype := *(**structType)(unsafe.Pointer(&istruct))
2420 *typ = *prototype
2421 typ.Fields = fs
2422 if pkgpath != "" {
2423 typ.PkgPath = newName(pkgpath, "", false, false)
2424 }
2425
2426
2427 if ts, ok := structLookupCache.m.Load(hash); ok {
2428 for _, st := range ts.([]Type) {
2429 t := st.common()
2430 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2431 return toType(t)
2432 }
2433 }
2434 }
2435
2436
2437 structLookupCache.Lock()
2438 defer structLookupCache.Unlock()
2439 if ts, ok := structLookupCache.m.Load(hash); ok {
2440 for _, st := range ts.([]Type) {
2441 t := st.common()
2442 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2443 return toType(t)
2444 }
2445 }
2446 }
2447
2448 addToCache := func(t Type) Type {
2449 var ts []Type
2450 if ti, ok := structLookupCache.m.Load(hash); ok {
2451 ts = ti.([]Type)
2452 }
2453 structLookupCache.m.Store(hash, append(ts, t))
2454 return t
2455 }
2456
2457
2458 for _, t := range typesByString(str) {
2459 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2460
2461
2462
2463 return addToCache(toType(t))
2464 }
2465 }
2466
2467 typ.Str = resolveReflectName(newName(str, "", false, false))
2468 if isRegularMemory(toType(&typ.Type)) {
2469 typ.TFlag = abi.TFlagRegularMemory
2470 } else {
2471 typ.TFlag = 0
2472 }
2473 typ.Hash = hash
2474 typ.Size_ = size
2475 typ.PtrBytes = typeptrdata(&typ.Type)
2476 typ.Align_ = typalign
2477 typ.FieldAlign_ = typalign
2478 typ.PtrToThis = 0
2479 if len(methods) > 0 {
2480 typ.TFlag |= abi.TFlagUncommon
2481 }
2482
2483 if typ.PtrBytes == 0 {
2484 typ.GCData = nil
2485 } else if typ.PtrBytes <= abi.MaxPtrmaskBytes*8*goarch.PtrSize {
2486 bv := new(bitVector)
2487 addTypeBits(bv, 0, &typ.Type)
2488 typ.GCData = &bv.data[0]
2489 } else {
2490
2491
2492 typ.TFlag |= abi.TFlagGCMaskOnDemand
2493 typ.GCData = (*byte)(unsafe.Pointer(new(uintptr)))
2494 }
2495
2496 typ.Equal = nil
2497 if comparable {
2498 typ.Equal = func(p, q unsafe.Pointer) bool {
2499 for _, ft := range typ.Fields {
2500 pi := add(p, ft.Offset, "&x.field safe")
2501 qi := add(q, ft.Offset, "&x.field safe")
2502 if !ft.Typ.Equal(pi, qi) {
2503 return false
2504 }
2505 }
2506 return true
2507 }
2508 }
2509
2510 switch {
2511 case len(fs) == 1 && !fs[0].Typ.IfaceIndir():
2512
2513 typ.Kind_ |= abi.KindDirectIface
2514 default:
2515 typ.Kind_ &^= abi.KindDirectIface
2516 }
2517
2518 return addToCache(toType(&typ.Type))
2519 }
2520
2521 func embeddedIfaceMethStub() {
2522 panic("reflect: StructOf does not support methods of embedded interfaces")
2523 }
2524
2525
2526
2527
2528 func runtimeStructField(field StructField) (structField, string) {
2529 if field.Anonymous && field.PkgPath != "" {
2530 panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
2531 }
2532
2533 if field.IsExported() {
2534
2535
2536 c := field.Name[0]
2537 if 'a' <= c && c <= 'z' || c == '_' {
2538 panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
2539 }
2540 }
2541
2542 resolveReflectType(field.Type.common())
2543 f := structField{
2544 Name: newName(field.Name, string(field.Tag), field.IsExported(), field.Anonymous),
2545 Typ: field.Type.common(),
2546 Offset: 0,
2547 }
2548 return f, field.PkgPath
2549 }
2550
2551
2552
2553
2554 func typeptrdata(t *abi.Type) uintptr {
2555 switch t.Kind() {
2556 case abi.Struct:
2557 st := (*structType)(unsafe.Pointer(t))
2558
2559 field := -1
2560 for i := range st.Fields {
2561 ft := st.Fields[i].Typ
2562 if ft.Pointers() {
2563 field = i
2564 }
2565 }
2566 if field == -1 {
2567 return 0
2568 }
2569 f := st.Fields[field]
2570 return f.Offset + f.Typ.PtrBytes
2571
2572 default:
2573 panic("reflect.typeptrdata: unexpected type, " + stringFor(t))
2574 }
2575 }
2576
2577
2578
2579
2580
2581
2582 func ArrayOf(length int, elem Type) Type {
2583 if length < 0 {
2584 panic("reflect: negative length passed to ArrayOf")
2585 }
2586
2587 typ := elem.common()
2588
2589
2590 ckey := cacheKey{Array, typ, nil, uintptr(length)}
2591 if array, ok := lookupCache.Load(ckey); ok {
2592 return array.(Type)
2593 }
2594
2595
2596 s := "[" + strconv.Itoa(length) + "]" + stringFor(typ)
2597 for _, tt := range typesByString(s) {
2598 array := (*arrayType)(unsafe.Pointer(tt))
2599 if array.Elem == typ {
2600 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2601 return ti.(Type)
2602 }
2603 }
2604
2605
2606 var iarray any = [1]unsafe.Pointer{}
2607 prototype := *(**arrayType)(unsafe.Pointer(&iarray))
2608 array := *prototype
2609 array.TFlag = typ.TFlag & abi.TFlagRegularMemory
2610 array.Str = resolveReflectName(newName(s, "", false, false))
2611 array.Hash = fnv1(typ.Hash, '[')
2612 for n := uint32(length); n > 0; n >>= 8 {
2613 array.Hash = fnv1(array.Hash, byte(n))
2614 }
2615 array.Hash = fnv1(array.Hash, ']')
2616 array.Elem = typ
2617 array.PtrToThis = 0
2618 if typ.Size_ > 0 {
2619 max := ^uintptr(0) / typ.Size_
2620 if uintptr(length) > max {
2621 panic("reflect.ArrayOf: array size would exceed virtual address space")
2622 }
2623 }
2624 array.Size_ = typ.Size_ * uintptr(length)
2625 if length > 0 && typ.Pointers() {
2626 array.PtrBytes = typ.Size_*uintptr(length-1) + typ.PtrBytes
2627 } else {
2628 array.PtrBytes = 0
2629 }
2630 array.Align_ = typ.Align_
2631 array.FieldAlign_ = typ.FieldAlign_
2632 array.Len = uintptr(length)
2633 array.Slice = &(SliceOf(elem).(*rtype).t)
2634
2635 switch {
2636 case array.PtrBytes == 0:
2637
2638 array.GCData = nil
2639
2640 case length == 1:
2641
2642
2643 array.TFlag |= typ.TFlag & abi.TFlagGCMaskOnDemand
2644 array.GCData = typ.GCData
2645
2646 case array.PtrBytes <= abi.MaxPtrmaskBytes*8*goarch.PtrSize:
2647
2648 n := (array.PtrBytes/goarch.PtrSize + 7) / 8
2649
2650 n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
2651 mask := make([]byte, n)
2652 emitGCMask(mask, 0, typ, array.Len)
2653 array.GCData = &mask[0]
2654
2655 default:
2656
2657
2658 array.TFlag |= abi.TFlagGCMaskOnDemand
2659 array.GCData = (*byte)(unsafe.Pointer(new(uintptr)))
2660 }
2661
2662 etyp := typ
2663 esize := etyp.Size()
2664
2665 array.Equal = nil
2666 if eequal := etyp.Equal; eequal != nil {
2667 array.Equal = func(p, q unsafe.Pointer) bool {
2668 for i := 0; i < length; i++ {
2669 pi := arrayAt(p, i, esize, "i < length")
2670 qi := arrayAt(q, i, esize, "i < length")
2671 if !eequal(pi, qi) {
2672 return false
2673 }
2674
2675 }
2676 return true
2677 }
2678 }
2679
2680 switch {
2681 case length == 1 && !typ.IfaceIndir():
2682
2683 array.Kind_ |= abi.KindDirectIface
2684 default:
2685 array.Kind_ &^= abi.KindDirectIface
2686 }
2687
2688 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&array.Type))
2689 return ti.(Type)
2690 }
2691
2692 func appendVarint(x []byte, v uintptr) []byte {
2693 for ; v >= 0x80; v >>= 7 {
2694 x = append(x, byte(v|0x80))
2695 }
2696 x = append(x, byte(v))
2697 return x
2698 }
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718 func toType(t *abi.Type) Type {
2719 if t == nil {
2720 return nil
2721 }
2722 return toRType(t)
2723 }
2724
2725 type layoutKey struct {
2726 ftyp *funcType
2727 rcvr *abi.Type
2728 }
2729
2730 type layoutType struct {
2731 t *abi.Type
2732 framePool *sync.Pool
2733 abid abiDesc
2734 }
2735
2736 var layoutCache sync.Map
2737
2738
2739
2740
2741
2742
2743
2744
2745 func funcLayout(t *funcType, rcvr *abi.Type) (frametype *abi.Type, framePool *sync.Pool, abid abiDesc) {
2746 if t.Kind() != abi.Func {
2747 panic("reflect: funcLayout of non-func type " + stringFor(&t.Type))
2748 }
2749 if rcvr != nil && rcvr.Kind() == abi.Interface {
2750 panic("reflect: funcLayout with interface receiver " + stringFor(rcvr))
2751 }
2752 k := layoutKey{t, rcvr}
2753 if lti, ok := layoutCache.Load(k); ok {
2754 lt := lti.(layoutType)
2755 return lt.t, lt.framePool, lt.abid
2756 }
2757
2758
2759 abid = newAbiDesc(t, rcvr)
2760
2761
2762 x := &abi.Type{
2763 Align_: goarch.PtrSize,
2764
2765
2766
2767
2768 Size_: align(abid.retOffset+abid.ret.stackBytes, goarch.PtrSize),
2769 PtrBytes: uintptr(abid.stackPtrs.n) * goarch.PtrSize,
2770 }
2771 if abid.stackPtrs.n > 0 {
2772 x.GCData = &abid.stackPtrs.data[0]
2773 }
2774
2775 var s string
2776 if rcvr != nil {
2777 s = "methodargs(" + stringFor(rcvr) + ")(" + stringFor(&t.Type) + ")"
2778 } else {
2779 s = "funcargs(" + stringFor(&t.Type) + ")"
2780 }
2781 x.Str = resolveReflectName(newName(s, "", false, false))
2782
2783
2784 framePool = &sync.Pool{New: func() any {
2785 return unsafe_New(x)
2786 }}
2787 lti, _ := layoutCache.LoadOrStore(k, layoutType{
2788 t: x,
2789 framePool: framePool,
2790 abid: abid,
2791 })
2792 lt := lti.(layoutType)
2793 return lt.t, lt.framePool, lt.abid
2794 }
2795
2796
2797 type bitVector struct {
2798 n uint32
2799 data []byte
2800 }
2801
2802
2803 func (bv *bitVector) append(bit uint8) {
2804 if bv.n%(8*goarch.PtrSize) == 0 {
2805
2806
2807
2808 for i := 0; i < goarch.PtrSize; i++ {
2809 bv.data = append(bv.data, 0)
2810 }
2811 }
2812 bv.data[bv.n/8] |= bit << (bv.n % 8)
2813 bv.n++
2814 }
2815
2816 func addTypeBits(bv *bitVector, offset uintptr, t *abi.Type) {
2817 if !t.Pointers() {
2818 return
2819 }
2820
2821 switch Kind(t.Kind_ & abi.KindMask) {
2822 case Chan, Func, Map, Pointer, Slice, String, UnsafePointer:
2823
2824 for bv.n < uint32(offset/goarch.PtrSize) {
2825 bv.append(0)
2826 }
2827 bv.append(1)
2828
2829 case Interface:
2830
2831 for bv.n < uint32(offset/goarch.PtrSize) {
2832 bv.append(0)
2833 }
2834 bv.append(1)
2835 bv.append(1)
2836
2837 case Array:
2838
2839 tt := (*arrayType)(unsafe.Pointer(t))
2840 for i := 0; i < int(tt.Len); i++ {
2841 addTypeBits(bv, offset+uintptr(i)*tt.Elem.Size_, tt.Elem)
2842 }
2843
2844 case Struct:
2845
2846 tt := (*structType)(unsafe.Pointer(t))
2847 for i := range tt.Fields {
2848 f := &tt.Fields[i]
2849 addTypeBits(bv, offset+f.Offset, f.Typ)
2850 }
2851 }
2852 }
2853
2854
2855 func TypeFor[T any]() Type {
2856 var v T
2857 if t := TypeOf(v); t != nil {
2858 return t
2859 }
2860 return TypeOf((*T)(nil)).Elem()
2861 }
2862
View as plain text