1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package reflectlite implements lightweight version of reflect, not using
6// any package except for "runtime", "unsafe", and "internal/abi"
7package reflectlite
8
9import (
10	"internal/abi"
11	"unsafe"
12)
13
14// Type is the representation of a Go type.
15//
16// Not all methods apply to all kinds of types. Restrictions,
17// if any, are noted in the documentation for each method.
18// Use the Kind method to find out the kind of type before
19// calling kind-specific methods. Calling a method
20// inappropriate to the kind of type causes a run-time panic.
21//
22// Type values are comparable, such as with the == operator,
23// so they can be used as map keys.
24// Two Type values are equal if they represent identical types.
25type Type interface {
26	// Methods applicable to all types.
27
28	// Name returns the type's name within its package for a defined type.
29	// For other (non-defined) types it returns the empty string.
30	Name() string
31
32	// PkgPath returns a defined type's package path, that is, the import path
33	// that uniquely identifies the package, such as "encoding/base64".
34	// If the type was predeclared (string, error) or not defined (*T, struct{},
35	// []int, or A where A is an alias for a non-defined type), the package path
36	// will be the empty string.
37	PkgPath() string
38
39	// Size returns the number of bytes needed to store
40	// a value of the given type; it is analogous to unsafe.Sizeof.
41	Size() uintptr
42
43	// Kind returns the specific kind of this type.
44	Kind() Kind
45
46	// Implements reports whether the type implements the interface type u.
47	Implements(u Type) bool
48
49	// AssignableTo reports whether a value of the type is assignable to type u.
50	AssignableTo(u Type) bool
51
52	// Comparable reports whether values of this type are comparable.
53	Comparable() bool
54
55	// String returns a string representation of the type.
56	// The string representation may use shortened package names
57	// (e.g., base64 instead of "encoding/base64") and is not
58	// guaranteed to be unique among types. To test for type identity,
59	// compare the Types directly.
60	String() string
61
62	// Elem returns a type's element type.
63	// It panics if the type's Kind is not Ptr.
64	Elem() Type
65
66	common() *abi.Type
67	uncommon() *uncommonType
68}
69
70/*
71 * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
72 * A few are known to ../runtime/type.go to convey to debuggers.
73 * They are also known to ../runtime/type.go.
74 */
75
76// A Kind represents the specific kind of type that a Type represents.
77// The zero Kind is not a valid kind.
78type Kind = abi.Kind
79
80const Ptr = abi.Pointer
81
82const (
83	// Import-and-export these constants as necessary
84	Interface = abi.Interface
85	Slice     = abi.Slice
86	String    = abi.String
87	Struct    = abi.Struct
88)
89
90type nameOff = abi.NameOff
91type typeOff = abi.TypeOff
92type textOff = abi.TextOff
93
94type rtype struct {
95	*abi.Type
96}
97
98// uncommonType is present only for defined types or types with methods
99// (if T is a defined type, the uncommonTypes for T and *T have methods).
100// Using a pointer to this struct reduces the overall size required
101// to describe a non-defined type with no methods.
102type uncommonType = abi.UncommonType
103
104// arrayType represents a fixed array type.
105type arrayType = abi.ArrayType
106
107// chanType represents a channel type.
108type chanType = abi.ChanType
109
110type funcType = abi.FuncType
111
112type interfaceType = abi.InterfaceType
113
114// ptrType represents a pointer type.
115type ptrType = abi.PtrType
116
117// sliceType represents a slice type.
118type sliceType = abi.SliceType
119
120// structType represents a struct type.
121type structType = abi.StructType
122
123// name is an encoded type name with optional extra data.
124//
125// The first byte is a bit field containing:
126//
127//	1<<0 the name is exported
128//	1<<1 tag data follows the name
129//	1<<2 pkgPath nameOff follows the name and tag
130//
131// The next two bytes are the data length:
132//
133//	l := uint16(data[1])<<8 | uint16(data[2])
134//
135// Bytes [3:3+l] are the string data.
136//
137// If tag data follows then bytes 3+l and 3+l+1 are the tag length,
138// with the data following.
139//
140// If the import path follows, then 4 bytes at the end of
141// the data form a nameOff. The import path is only set for concrete
142// methods that are defined in a different package than their type.
143//
144// If a name starts with "*", then the exported bit represents
145// whether the pointed to type is exported.
146type name struct {
147	bytes *byte
148}
149
150func (n name) data(off int, whySafe string) *byte {
151	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
152}
153
154func (n name) isExported() bool {
155	return (*n.bytes)&(1<<0) != 0
156}
157
158func (n name) hasTag() bool {
159	return (*n.bytes)&(1<<1) != 0
160}
161
162func (n name) embedded() bool {
163	return (*n.bytes)&(1<<3) != 0
164}
165
166// readVarint parses a varint as encoded by encoding/binary.
167// It returns the number of encoded bytes and the encoded value.
168func (n name) readVarint(off int) (int, int) {
169	v := 0
170	for i := 0; ; i++ {
171		x := *n.data(off+i, "read varint")
172		v += int(x&0x7f) << (7 * i)
173		if x&0x80 == 0 {
174			return i + 1, v
175		}
176	}
177}
178
179func (n name) name() string {
180	if n.bytes == nil {
181		return ""
182	}
183	i, l := n.readVarint(1)
184	return unsafe.String(n.data(1+i, "non-empty string"), l)
185}
186
187func (n name) tag() string {
188	if !n.hasTag() {
189		return ""
190	}
191	i, l := n.readVarint(1)
192	i2, l2 := n.readVarint(1 + i + l)
193	return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
194}
195
196func pkgPath(n abi.Name) string {
197	if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
198		return ""
199	}
200	i, l := n.ReadVarint(1)
201	off := 1 + i + l
202	if n.HasTag() {
203		i2, l2 := n.ReadVarint(off)
204		off += i2 + l2
205	}
206	var nameOff int32
207	// Note that this field may not be aligned in memory,
208	// so we cannot use a direct int32 assignment here.
209	copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
210	pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
211	return pkgPathName.name()
212}
213
214/*
215 * The compiler knows the exact layout of all the data structures above.
216 * The compiler does not know about the data structures and methods below.
217 */
218
219// resolveNameOff resolves a name offset from a base pointer.
220// The (*rtype).nameOff method is a convenience wrapper for this function.
221// Implemented in the runtime package.
222//
223//go:noescape
224func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
225
226// resolveTypeOff resolves an *rtype offset from a base type.
227// The (*rtype).typeOff method is a convenience wrapper for this function.
228// Implemented in the runtime package.
229//
230//go:noescape
231func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
232
233func (t rtype) nameOff(off nameOff) abi.Name {
234	return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
235}
236
237func (t rtype) typeOff(off typeOff) *abi.Type {
238	return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
239}
240
241func (t rtype) uncommon() *uncommonType {
242	return t.Uncommon()
243}
244
245func (t rtype) String() string {
246	s := t.nameOff(t.Str).Name()
247	if t.TFlag&abi.TFlagExtraStar != 0 {
248		return s[1:]
249	}
250	return s
251}
252
253func (t rtype) common() *abi.Type { return t.Type }
254
255func (t rtype) exportedMethods() []abi.Method {
256	ut := t.uncommon()
257	if ut == nil {
258		return nil
259	}
260	return ut.ExportedMethods()
261}
262
263func (t rtype) NumMethod() int {
264	tt := t.Type.InterfaceType()
265	if tt != nil {
266		return tt.NumMethod()
267	}
268	return len(t.exportedMethods())
269}
270
271func (t rtype) PkgPath() string {
272	if t.TFlag&abi.TFlagNamed == 0 {
273		return ""
274	}
275	ut := t.uncommon()
276	if ut == nil {
277		return ""
278	}
279	return t.nameOff(ut.PkgPath).Name()
280}
281
282func (t rtype) Name() string {
283	if !t.HasName() {
284		return ""
285	}
286	s := t.String()
287	i := len(s) - 1
288	sqBrackets := 0
289	for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
290		switch s[i] {
291		case ']':
292			sqBrackets++
293		case '[':
294			sqBrackets--
295		}
296		i--
297	}
298	return s[i+1:]
299}
300
301func toRType(t *abi.Type) rtype {
302	return rtype{t}
303}
304
305func elem(t *abi.Type) *abi.Type {
306	et := t.Elem()
307	if et != nil {
308		return et
309	}
310	panic("reflect: Elem of invalid type " + toRType(t).String())
311}
312
313func (t rtype) Elem() Type {
314	return toType(elem(t.common()))
315}
316
317func (t rtype) In(i int) Type {
318	tt := t.Type.FuncType()
319	if tt == nil {
320		panic("reflect: In of non-func type")
321	}
322	return toType(tt.InSlice()[i])
323}
324
325func (t rtype) Key() Type {
326	tt := t.Type.MapType()
327	if tt == nil {
328		panic("reflect: Key of non-map type")
329	}
330	return toType(tt.Key)
331}
332
333func (t rtype) Len() int {
334	tt := t.Type.ArrayType()
335	if tt == nil {
336		panic("reflect: Len of non-array type")
337	}
338	return int(tt.Len)
339}
340
341func (t rtype) NumField() int {
342	tt := t.Type.StructType()
343	if tt == nil {
344		panic("reflect: NumField of non-struct type")
345	}
346	return len(tt.Fields)
347}
348
349func (t rtype) NumIn() int {
350	tt := t.Type.FuncType()
351	if tt == nil {
352		panic("reflect: NumIn of non-func type")
353	}
354	return int(tt.InCount)
355}
356
357func (t rtype) NumOut() int {
358	tt := t.Type.FuncType()
359	if tt == nil {
360		panic("reflect: NumOut of non-func type")
361	}
362	return tt.NumOut()
363}
364
365func (t rtype) Out(i int) Type {
366	tt := t.Type.FuncType()
367	if tt == nil {
368		panic("reflect: Out of non-func type")
369	}
370	return toType(tt.OutSlice()[i])
371}
372
373// add returns p+x.
374//
375// The whySafe string is ignored, so that the function still inlines
376// as efficiently as p+x, but all call sites should use the string to
377// record why the addition is safe, which is to say why the addition
378// does not cause x to advance to the very end of p's allocation
379// and therefore point incorrectly at the next block in memory.
380func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
381	return unsafe.Pointer(uintptr(p) + x)
382}
383
384// TypeOf returns the reflection Type that represents the dynamic type of i.
385// If i is a nil interface value, TypeOf returns nil.
386func TypeOf(i any) Type {
387	return toType(abi.TypeOf(i))
388}
389
390func (t rtype) Implements(u Type) bool {
391	if u == nil {
392		panic("reflect: nil type passed to Type.Implements")
393	}
394	if u.Kind() != Interface {
395		panic("reflect: non-interface type passed to Type.Implements")
396	}
397	return implements(u.common(), t.common())
398}
399
400func (t rtype) AssignableTo(u Type) bool {
401	if u == nil {
402		panic("reflect: nil type passed to Type.AssignableTo")
403	}
404	uu := u.common()
405	tt := t.common()
406	return directlyAssignable(uu, tt) || implements(uu, tt)
407}
408
409func (t rtype) Comparable() bool {
410	return t.Equal != nil
411}
412
413// implements reports whether the type V implements the interface type T.
414func implements(T, V *abi.Type) bool {
415	t := T.InterfaceType()
416	if t == nil {
417		return false
418	}
419	if len(t.Methods) == 0 {
420		return true
421	}
422	rT := toRType(T)
423	rV := toRType(V)
424
425	// The same algorithm applies in both cases, but the
426	// method tables for an interface type and a concrete type
427	// are different, so the code is duplicated.
428	// In both cases the algorithm is a linear scan over the two
429	// lists - T's methods and V's methods - simultaneously.
430	// Since method tables are stored in a unique sorted order
431	// (alphabetical, with no duplicate method names), the scan
432	// through V's methods must hit a match for each of T's
433	// methods along the way, or else V does not implement T.
434	// This lets us run the scan in overall linear time instead of
435	// the quadratic time  a naive search would require.
436	// See also ../runtime/iface.go.
437	if V.Kind() == Interface {
438		v := (*interfaceType)(unsafe.Pointer(V))
439		i := 0
440		for j := 0; j < len(v.Methods); j++ {
441			tm := &t.Methods[i]
442			tmName := rT.nameOff(tm.Name)
443			vm := &v.Methods[j]
444			vmName := rV.nameOff(vm.Name)
445			if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
446				if !tmName.IsExported() {
447					tmPkgPath := pkgPath(tmName)
448					if tmPkgPath == "" {
449						tmPkgPath = t.PkgPath.Name()
450					}
451					vmPkgPath := pkgPath(vmName)
452					if vmPkgPath == "" {
453						vmPkgPath = v.PkgPath.Name()
454					}
455					if tmPkgPath != vmPkgPath {
456						continue
457					}
458				}
459				if i++; i >= len(t.Methods) {
460					return true
461				}
462			}
463		}
464		return false
465	}
466
467	v := V.Uncommon()
468	if v == nil {
469		return false
470	}
471	i := 0
472	vmethods := v.Methods()
473	for j := 0; j < int(v.Mcount); j++ {
474		tm := &t.Methods[i]
475		tmName := rT.nameOff(tm.Name)
476		vm := vmethods[j]
477		vmName := rV.nameOff(vm.Name)
478		if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
479			if !tmName.IsExported() {
480				tmPkgPath := pkgPath(tmName)
481				if tmPkgPath == "" {
482					tmPkgPath = t.PkgPath.Name()
483				}
484				vmPkgPath := pkgPath(vmName)
485				if vmPkgPath == "" {
486					vmPkgPath = rV.nameOff(v.PkgPath).Name()
487				}
488				if tmPkgPath != vmPkgPath {
489					continue
490				}
491			}
492			if i++; i >= len(t.Methods) {
493				return true
494			}
495		}
496	}
497	return false
498}
499
500// directlyAssignable reports whether a value x of type V can be directly
501// assigned (using memmove) to a value of type T.
502// https://golang.org/doc/go_spec.html#Assignability
503// Ignoring the interface rules (implemented elsewhere)
504// and the ideal constant rules (no ideal constants at run time).
505func directlyAssignable(T, V *abi.Type) bool {
506	// x's type V is identical to T?
507	if T == V {
508		return true
509	}
510
511	// Otherwise at least one of T and V must not be defined
512	// and they must have the same kind.
513	if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
514		return false
515	}
516
517	// x's type T and V must  have identical underlying types.
518	return haveIdenticalUnderlyingType(T, V, true)
519}
520
521func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
522	if cmpTags {
523		return T == V
524	}
525
526	if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
527		return false
528	}
529
530	return haveIdenticalUnderlyingType(T, V, false)
531}
532
533func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
534	if T == V {
535		return true
536	}
537
538	kind := T.Kind()
539	if kind != V.Kind() {
540		return false
541	}
542
543	// Non-composite types of equal kind have same underlying type
544	// (the predefined instance of the type).
545	if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
546		return true
547	}
548
549	// Composite types.
550	switch kind {
551	case abi.Array:
552		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
553
554	case abi.Chan:
555		// Special case:
556		// x is a bidirectional channel value, T is a channel type,
557		// and x's type V and T have identical element types.
558		if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
559			return true
560		}
561
562		// Otherwise continue test for identical underlying type.
563		return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
564
565	case abi.Func:
566		t := (*funcType)(unsafe.Pointer(T))
567		v := (*funcType)(unsafe.Pointer(V))
568		if t.OutCount != v.OutCount || t.InCount != v.InCount {
569			return false
570		}
571		for i := 0; i < t.NumIn(); i++ {
572			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
573				return false
574			}
575		}
576		for i := 0; i < t.NumOut(); i++ {
577			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
578				return false
579			}
580		}
581		return true
582
583	case Interface:
584		t := (*interfaceType)(unsafe.Pointer(T))
585		v := (*interfaceType)(unsafe.Pointer(V))
586		if len(t.Methods) == 0 && len(v.Methods) == 0 {
587			return true
588		}
589		// Might have the same methods but still
590		// need a run time conversion.
591		return false
592
593	case abi.Map:
594		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
595
596	case Ptr, abi.Slice:
597		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
598
599	case abi.Struct:
600		t := (*structType)(unsafe.Pointer(T))
601		v := (*structType)(unsafe.Pointer(V))
602		if len(t.Fields) != len(v.Fields) {
603			return false
604		}
605		if t.PkgPath.Name() != v.PkgPath.Name() {
606			return false
607		}
608		for i := range t.Fields {
609			tf := &t.Fields[i]
610			vf := &v.Fields[i]
611			if tf.Name.Name() != vf.Name.Name() {
612				return false
613			}
614			if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
615				return false
616			}
617			if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
618				return false
619			}
620			if tf.Offset != vf.Offset {
621				return false
622			}
623			if tf.Embedded() != vf.Embedded() {
624				return false
625			}
626		}
627		return true
628	}
629
630	return false
631}
632
633// toType converts from a *rtype to a Type that can be returned
634// to the client of package reflect. In gc, the only concern is that
635// a nil *rtype must be replaced by a nil Type, but in gccgo this
636// function takes care of ensuring that multiple *rtype for the same
637// type are coalesced into a single Type.
638func toType(t *abi.Type) Type {
639	if t == nil {
640		return nil
641	}
642	return toRType(t)
643}
644