Source file src/pkg/internal/reflectlite/type.go
1
2
3
4
5
6
7 package reflectlite
8
9 import (
10 "unsafe"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24 type Type interface {
25
26
27
28
29 Name() string
30
31
32
33
34
35
36 PkgPath() string
37
38
39
40 Size() uintptr
41
42
43 Kind() Kind
44
45
46 Implements(u Type) bool
47
48
49 AssignableTo(u Type) bool
50
51
52 Comparable() bool
53
54
55
56
57
58
59 String() string
60
61
62
63 Elem() Type
64
65 common() *rtype
66 uncommon() *uncommonType
67 }
68
69
74
75
76
77 type Kind uint
78
79 const (
80 Invalid Kind = iota
81 Bool
82 Int
83 Int8
84 Int16
85 Int32
86 Int64
87 Uint
88 Uint8
89 Uint16
90 Uint32
91 Uint64
92 Uintptr
93 Float32
94 Float64
95 Complex64
96 Complex128
97 Array
98 Chan
99 Func
100 Interface
101 Map
102 Ptr
103 Slice
104 String
105 Struct
106 UnsafePointer
107 )
108
109
110
111
112
113
114
115
116 type tflag uint8
117
118 const (
119
120
121
122
123
124
125
126
127
128
129
130 tflagUncommon tflag = 1 << 0
131
132
133
134
135
136 tflagExtraStar tflag = 1 << 1
137
138
139 tflagNamed tflag = 1 << 2
140 )
141
142
143
144
145
146 type rtype struct {
147 size uintptr
148 ptrdata uintptr
149 hash uint32
150 tflag tflag
151 align uint8
152 fieldAlign uint8
153 kind uint8
154 alg *typeAlg
155 gcdata *byte
156 str nameOff
157 ptrToThis typeOff
158 }
159
160
161 type typeAlg struct {
162
163
164 hash func(unsafe.Pointer, uintptr) uintptr
165
166
167 equal func(unsafe.Pointer, unsafe.Pointer) bool
168 }
169
170
171 type method struct {
172 name nameOff
173 mtyp typeOff
174 ifn textOff
175 tfn textOff
176 }
177
178
179
180
181
182 type uncommonType struct {
183 pkgPath nameOff
184 mcount uint16
185 xcount uint16
186 moff uint32
187 _ uint32
188 }
189
190
191 type chanDir int
192
193 const (
194 recvDir chanDir = 1 << iota
195 sendDir
196 bothDir = recvDir | sendDir
197 )
198
199
200 type arrayType struct {
201 rtype
202 elem *rtype
203 slice *rtype
204 len uintptr
205 }
206
207
208 type chanType struct {
209 rtype
210 elem *rtype
211 dir uintptr
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225 type funcType struct {
226 rtype
227 inCount uint16
228 outCount uint16
229 }
230
231
232 type imethod struct {
233 name nameOff
234 typ typeOff
235 }
236
237
238 type interfaceType struct {
239 rtype
240 pkgPath name
241 methods []imethod
242 }
243
244
245 type mapType struct {
246 rtype
247 key *rtype
248 elem *rtype
249 bucket *rtype
250 keysize uint8
251 valuesize uint8
252 bucketsize uint16
253 flags uint32
254 }
255
256
257 type ptrType struct {
258 rtype
259 elem *rtype
260 }
261
262
263 type sliceType struct {
264 rtype
265 elem *rtype
266 }
267
268
269 type structField struct {
270 name name
271 typ *rtype
272 offsetEmbed uintptr
273 }
274
275 func (f *structField) offset() uintptr {
276 return f.offsetEmbed >> 1
277 }
278
279 func (f *structField) embedded() bool {
280 return f.offsetEmbed&1 != 0
281 }
282
283
284 type structType struct {
285 rtype
286 pkgPath name
287 fields []structField
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 type name struct {
314 bytes *byte
315 }
316
317 func (n name) data(off int, whySafe string) *byte {
318 return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
319 }
320
321 func (n name) isExported() bool {
322 return (*n.bytes)&(1<<0) != 0
323 }
324
325 func (n name) nameLen() int {
326 return int(uint16(*n.data(1, "name len field"))<<8 | uint16(*n.data(2, "name len field")))
327 }
328
329 func (n name) tagLen() int {
330 if *n.data(0, "name flag field")&(1<<1) == 0 {
331 return 0
332 }
333 off := 3 + n.nameLen()
334 return int(uint16(*n.data(off, "name taglen field"))<<8 | uint16(*n.data(off+1, "name taglen field")))
335 }
336
337 func (n name) name() (s string) {
338 if n.bytes == nil {
339 return
340 }
341 b := (*[4]byte)(unsafe.Pointer(n.bytes))
342
343 hdr := (*stringHeader)(unsafe.Pointer(&s))
344 hdr.Data = unsafe.Pointer(&b[3])
345 hdr.Len = int(b[1])<<8 | int(b[2])
346 return s
347 }
348
349 func (n name) tag() (s string) {
350 tl := n.tagLen()
351 if tl == 0 {
352 return ""
353 }
354 nl := n.nameLen()
355 hdr := (*stringHeader)(unsafe.Pointer(&s))
356 hdr.Data = unsafe.Pointer(n.data(3+nl+2, "non-empty string"))
357 hdr.Len = tl
358 return s
359 }
360
361 func (n name) pkgPath() string {
362 if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
363 return ""
364 }
365 off := 3 + n.nameLen()
366 if tl := n.tagLen(); tl > 0 {
367 off += 2 + tl
368 }
369 var nameOff int32
370
371
372 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
373 pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
374 return pkgPathName.name()
375 }
376
377
381
382 const (
383 kindDirectIface = 1 << 5
384 kindGCProg = 1 << 6
385 kindMask = (1 << 5) - 1
386 )
387
388 func (t *uncommonType) methods() []method {
389 if t.mcount == 0 {
390 return nil
391 }
392 return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
393 }
394
395 func (t *uncommonType) exportedMethods() []method {
396 if t.xcount == 0 {
397 return nil
398 }
399 return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
400 }
401
402
403
404
405 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
406
407
408
409
410 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
411
412 type nameOff int32
413 type typeOff int32
414 type textOff int32
415
416 func (t *rtype) nameOff(off nameOff) name {
417 return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
418 }
419
420 func (t *rtype) typeOff(off typeOff) *rtype {
421 return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
422 }
423
424 func (t *rtype) uncommon() *uncommonType {
425 if t.tflag&tflagUncommon == 0 {
426 return nil
427 }
428 switch t.Kind() {
429 case Struct:
430 return &(*structTypeUncommon)(unsafe.Pointer(t)).u
431 case Ptr:
432 type u struct {
433 ptrType
434 u uncommonType
435 }
436 return &(*u)(unsafe.Pointer(t)).u
437 case Func:
438 type u struct {
439 funcType
440 u uncommonType
441 }
442 return &(*u)(unsafe.Pointer(t)).u
443 case Slice:
444 type u struct {
445 sliceType
446 u uncommonType
447 }
448 return &(*u)(unsafe.Pointer(t)).u
449 case Array:
450 type u struct {
451 arrayType
452 u uncommonType
453 }
454 return &(*u)(unsafe.Pointer(t)).u
455 case Chan:
456 type u struct {
457 chanType
458 u uncommonType
459 }
460 return &(*u)(unsafe.Pointer(t)).u
461 case Map:
462 type u struct {
463 mapType
464 u uncommonType
465 }
466 return &(*u)(unsafe.Pointer(t)).u
467 case Interface:
468 type u struct {
469 interfaceType
470 u uncommonType
471 }
472 return &(*u)(unsafe.Pointer(t)).u
473 default:
474 type u struct {
475 rtype
476 u uncommonType
477 }
478 return &(*u)(unsafe.Pointer(t)).u
479 }
480 }
481
482 func (t *rtype) String() string {
483 s := t.nameOff(t.str).name()
484 if t.tflag&tflagExtraStar != 0 {
485 return s[1:]
486 }
487 return s
488 }
489
490 func (t *rtype) Size() uintptr { return t.size }
491
492 func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
493
494 func (t *rtype) pointers() bool { return t.ptrdata != 0 }
495
496 func (t *rtype) common() *rtype { return t }
497
498 func (t *rtype) exportedMethods() []method {
499 ut := t.uncommon()
500 if ut == nil {
501 return nil
502 }
503 return ut.exportedMethods()
504 }
505
506 func (t *rtype) NumMethod() int {
507 if t.Kind() == Interface {
508 tt := (*interfaceType)(unsafe.Pointer(t))
509 return tt.NumMethod()
510 }
511 return len(t.exportedMethods())
512 }
513
514 func (t *rtype) PkgPath() string {
515 if t.tflag&tflagNamed == 0 {
516 return ""
517 }
518 ut := t.uncommon()
519 if ut == nil {
520 return ""
521 }
522 return t.nameOff(ut.pkgPath).name()
523 }
524
525 func (t *rtype) Name() string {
526 if t.tflag&tflagNamed == 0 {
527 return ""
528 }
529 s := t.String()
530 i := len(s) - 1
531 for i >= 0 && s[i] != '.' {
532 i--
533 }
534 return s[i+1:]
535 }
536
537 func (t *rtype) chanDir() chanDir {
538 if t.Kind() != Chan {
539 panic("reflect: chanDir of non-chan type")
540 }
541 tt := (*chanType)(unsafe.Pointer(t))
542 return chanDir(tt.dir)
543 }
544
545 func (t *rtype) Elem() Type {
546 switch t.Kind() {
547 case Array:
548 tt := (*arrayType)(unsafe.Pointer(t))
549 return toType(tt.elem)
550 case Chan:
551 tt := (*chanType)(unsafe.Pointer(t))
552 return toType(tt.elem)
553 case Map:
554 tt := (*mapType)(unsafe.Pointer(t))
555 return toType(tt.elem)
556 case Ptr:
557 tt := (*ptrType)(unsafe.Pointer(t))
558 return toType(tt.elem)
559 case Slice:
560 tt := (*sliceType)(unsafe.Pointer(t))
561 return toType(tt.elem)
562 }
563 panic("reflect: Elem of invalid type")
564 }
565
566 func (t *rtype) In(i int) Type {
567 if t.Kind() != Func {
568 panic("reflect: In of non-func type")
569 }
570 tt := (*funcType)(unsafe.Pointer(t))
571 return toType(tt.in()[i])
572 }
573
574 func (t *rtype) Key() Type {
575 if t.Kind() != Map {
576 panic("reflect: Key of non-map type")
577 }
578 tt := (*mapType)(unsafe.Pointer(t))
579 return toType(tt.key)
580 }
581
582 func (t *rtype) Len() int {
583 if t.Kind() != Array {
584 panic("reflect: Len of non-array type")
585 }
586 tt := (*arrayType)(unsafe.Pointer(t))
587 return int(tt.len)
588 }
589
590 func (t *rtype) NumField() int {
591 if t.Kind() != Struct {
592 panic("reflect: NumField of non-struct type")
593 }
594 tt := (*structType)(unsafe.Pointer(t))
595 return len(tt.fields)
596 }
597
598 func (t *rtype) NumIn() int {
599 if t.Kind() != Func {
600 panic("reflect: NumIn of non-func type")
601 }
602 tt := (*funcType)(unsafe.Pointer(t))
603 return int(tt.inCount)
604 }
605
606 func (t *rtype) NumOut() int {
607 if t.Kind() != Func {
608 panic("reflect: NumOut of non-func type")
609 }
610 tt := (*funcType)(unsafe.Pointer(t))
611 return len(tt.out())
612 }
613
614 func (t *rtype) Out(i int) Type {
615 if t.Kind() != Func {
616 panic("reflect: Out of non-func type")
617 }
618 tt := (*funcType)(unsafe.Pointer(t))
619 return toType(tt.out()[i])
620 }
621
622 func (t *funcType) in() []*rtype {
623 uadd := unsafe.Sizeof(*t)
624 if t.tflag&tflagUncommon != 0 {
625 uadd += unsafe.Sizeof(uncommonType{})
626 }
627 if t.inCount == 0 {
628 return nil
629 }
630 return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount]
631 }
632
633 func (t *funcType) out() []*rtype {
634 uadd := unsafe.Sizeof(*t)
635 if t.tflag&tflagUncommon != 0 {
636 uadd += unsafe.Sizeof(uncommonType{})
637 }
638 outCount := t.outCount & (1<<15 - 1)
639 if outCount == 0 {
640 return nil
641 }
642 return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount]
643 }
644
645
646
647
648
649
650
651
652 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
653 return unsafe.Pointer(uintptr(p) + x)
654 }
655
656
657 func (t *interfaceType) NumMethod() int { return len(t.methods) }
658
659
660
661 func TypeOf(i interface{}) Type {
662 eface := *(*emptyInterface)(unsafe.Pointer(&i))
663 return toType(eface.typ)
664 }
665
666 func (t *rtype) Implements(u Type) bool {
667 if u == nil {
668 panic("reflect: nil type passed to Type.Implements")
669 }
670 if u.Kind() != Interface {
671 panic("reflect: non-interface type passed to Type.Implements")
672 }
673 return implements(u.(*rtype), t)
674 }
675
676 func (t *rtype) AssignableTo(u Type) bool {
677 if u == nil {
678 panic("reflect: nil type passed to Type.AssignableTo")
679 }
680 uu := u.(*rtype)
681 return directlyAssignable(uu, t) || implements(uu, t)
682 }
683
684 func (t *rtype) Comparable() bool {
685 return t.alg != nil && t.alg.equal != nil
686 }
687
688
689 func implements(T, V *rtype) bool {
690 if T.Kind() != Interface {
691 return false
692 }
693 t := (*interfaceType)(unsafe.Pointer(T))
694 if len(t.methods) == 0 {
695 return true
696 }
697
698
699
700
701
702
703
704
705
706
707
708
709
710 if V.Kind() == Interface {
711 v := (*interfaceType)(unsafe.Pointer(V))
712 i := 0
713 for j := 0; j < len(v.methods); j++ {
714 tm := &t.methods[i]
715 tmName := t.nameOff(tm.name)
716 vm := &v.methods[j]
717 vmName := V.nameOff(vm.name)
718 if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
719 if !tmName.isExported() {
720 tmPkgPath := tmName.pkgPath()
721 if tmPkgPath == "" {
722 tmPkgPath = t.pkgPath.name()
723 }
724 vmPkgPath := vmName.pkgPath()
725 if vmPkgPath == "" {
726 vmPkgPath = v.pkgPath.name()
727 }
728 if tmPkgPath != vmPkgPath {
729 continue
730 }
731 }
732 if i++; i >= len(t.methods) {
733 return true
734 }
735 }
736 }
737 return false
738 }
739
740 v := V.uncommon()
741 if v == nil {
742 return false
743 }
744 i := 0
745 vmethods := v.methods()
746 for j := 0; j < int(v.mcount); j++ {
747 tm := &t.methods[i]
748 tmName := t.nameOff(tm.name)
749 vm := vmethods[j]
750 vmName := V.nameOff(vm.name)
751 if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
752 if !tmName.isExported() {
753 tmPkgPath := tmName.pkgPath()
754 if tmPkgPath == "" {
755 tmPkgPath = t.pkgPath.name()
756 }
757 vmPkgPath := vmName.pkgPath()
758 if vmPkgPath == "" {
759 vmPkgPath = V.nameOff(v.pkgPath).name()
760 }
761 if tmPkgPath != vmPkgPath {
762 continue
763 }
764 }
765 if i++; i >= len(t.methods) {
766 return true
767 }
768 }
769 }
770 return false
771 }
772
773
774
775
776
777
778 func directlyAssignable(T, V *rtype) bool {
779
780 if T == V {
781 return true
782 }
783
784
785
786 if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
787 return false
788 }
789
790
791 return haveIdenticalUnderlyingType(T, V, true)
792 }
793
794 func haveIdenticalType(T, V Type, cmpTags bool) bool {
795 if cmpTags {
796 return T == V
797 }
798
799 if T.Name() != V.Name() || T.Kind() != V.Kind() {
800 return false
801 }
802
803 return haveIdenticalUnderlyingType(T.common(), V.common(), false)
804 }
805
806 func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
807 if T == V {
808 return true
809 }
810
811 kind := T.Kind()
812 if kind != V.Kind() {
813 return false
814 }
815
816
817
818 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
819 return true
820 }
821
822
823 switch kind {
824 case Array:
825 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
826
827 case Chan:
828
829
830
831 if V.chanDir() == bothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
832 return true
833 }
834
835
836 return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
837
838 case Func:
839 t := (*funcType)(unsafe.Pointer(T))
840 v := (*funcType)(unsafe.Pointer(V))
841 if t.outCount != v.outCount || t.inCount != v.inCount {
842 return false
843 }
844 for i := 0; i < t.NumIn(); i++ {
845 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
846 return false
847 }
848 }
849 for i := 0; i < t.NumOut(); i++ {
850 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
851 return false
852 }
853 }
854 return true
855
856 case Interface:
857 t := (*interfaceType)(unsafe.Pointer(T))
858 v := (*interfaceType)(unsafe.Pointer(V))
859 if len(t.methods) == 0 && len(v.methods) == 0 {
860 return true
861 }
862
863
864 return false
865
866 case Map:
867 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
868
869 case Ptr, Slice:
870 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
871
872 case Struct:
873 t := (*structType)(unsafe.Pointer(T))
874 v := (*structType)(unsafe.Pointer(V))
875 if len(t.fields) != len(v.fields) {
876 return false
877 }
878 if t.pkgPath.name() != v.pkgPath.name() {
879 return false
880 }
881 for i := range t.fields {
882 tf := &t.fields[i]
883 vf := &v.fields[i]
884 if tf.name.name() != vf.name.name() {
885 return false
886 }
887 if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
888 return false
889 }
890 if cmpTags && tf.name.tag() != vf.name.tag() {
891 return false
892 }
893 if tf.offsetEmbed != vf.offsetEmbed {
894 return false
895 }
896 }
897 return true
898 }
899
900 return false
901 }
902
903 type structTypeUncommon struct {
904 structType
905 u uncommonType
906 }
907
908
909
910
911
912
913 func toType(t *rtype) Type {
914 if t == nil {
915 return nil
916 }
917 return t
918 }
919
920
921 func ifaceIndir(t *rtype) bool {
922 return t.kind&kindDirectIface == 0
923 }
924
View as plain text