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