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