github.com/bir3/gocompiler@v0.9.2202/src/internal/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/bir3/gocompiler/src/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. 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 // 237 //go:noescape 238 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer 239 240 // resolveTypeOff resolves an *rtype offset from a base type. 241 // The (*rtype).typeOff method is a convenience wrapper for this function. 242 // Implemented in the runtime package. 243 // 244 //go:noescape 245 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer 246 247 func (t rtype) nameOff(off nameOff) abi.Name { 248 return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))} 249 } 250 251 func (t rtype) typeOff(off typeOff) *abi.Type { 252 return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off))) 253 } 254 255 func (t rtype) uncommon() *uncommonType { 256 return t.Uncommon() 257 } 258 259 func (t rtype) String() string { 260 s := t.nameOff(t.Str).Name() 261 if t.TFlag&abi.TFlagExtraStar != 0 { 262 return s[1:] 263 } 264 return s 265 } 266 267 func (t rtype) common() *abi.Type { return t.Type } 268 269 func (t rtype) exportedMethods() []abi.Method { 270 ut := t.uncommon() 271 if ut == nil { 272 return nil 273 } 274 return ut.ExportedMethods() 275 } 276 277 func (t rtype) NumMethod() int { 278 tt := t.Type.InterfaceType() 279 if tt != nil { 280 return tt.NumMethod() 281 } 282 return len(t.exportedMethods()) 283 } 284 285 func (t rtype) PkgPath() string { 286 if t.TFlag&abi.TFlagNamed == 0 { 287 return "" 288 } 289 ut := t.uncommon() 290 if ut == nil { 291 return "" 292 } 293 return t.nameOff(ut.PkgPath).Name() 294 } 295 296 func (t rtype) Name() string { 297 if !t.HasName() { 298 return "" 299 } 300 s := t.String() 301 i := len(s) - 1 302 sqBrackets := 0 303 for i >= 0 && (s[i] != '.' || sqBrackets != 0) { 304 switch s[i] { 305 case ']': 306 sqBrackets++ 307 case '[': 308 sqBrackets-- 309 } 310 i-- 311 } 312 return s[i+1:] 313 } 314 315 func toRType(t *abi.Type) rtype { 316 return rtype{t} 317 } 318 319 func elem(t *abi.Type) *abi.Type { 320 et := t.Elem() 321 if et != nil { 322 return et 323 } 324 panic("reflect: Elem of invalid type " + toRType(t).String()) 325 } 326 327 func (t rtype) Elem() Type { 328 return toType(elem(t.common())) 329 } 330 331 func (t rtype) In(i int) Type { 332 tt := t.Type.FuncType() 333 if tt == nil { 334 panic("reflect: In of non-func type") 335 } 336 return toType(tt.InSlice()[i]) 337 } 338 339 func (t rtype) Key() Type { 340 tt := t.Type.MapType() 341 if tt == nil { 342 panic("reflect: Key of non-map type") 343 } 344 return toType(tt.Key) 345 } 346 347 func (t rtype) Len() int { 348 tt := t.Type.ArrayType() 349 if tt == nil { 350 panic("reflect: Len of non-array type") 351 } 352 return int(tt.Len) 353 } 354 355 func (t rtype) NumField() int { 356 tt := t.Type.StructType() 357 if tt == nil { 358 panic("reflect: NumField of non-struct type") 359 } 360 return len(tt.Fields) 361 } 362 363 func (t rtype) NumIn() int { 364 tt := t.Type.FuncType() 365 if tt == nil { 366 panic("reflect: NumIn of non-func type") 367 } 368 return int(tt.InCount) 369 } 370 371 func (t rtype) NumOut() int { 372 tt := t.Type.FuncType() 373 if tt == nil { 374 panic("reflect: NumOut of non-func type") 375 } 376 return tt.NumOut() 377 } 378 379 func (t rtype) Out(i int) Type { 380 tt := t.Type.FuncType() 381 if tt == nil { 382 panic("reflect: Out of non-func type") 383 } 384 return toType(tt.OutSlice()[i]) 385 } 386 387 // add returns p+x. 388 // 389 // The whySafe string is ignored, so that the function still inlines 390 // as efficiently as p+x, but all call sites should use the string to 391 // record why the addition is safe, which is to say why the addition 392 // does not cause x to advance to the very end of p's allocation 393 // and therefore point incorrectly at the next block in memory. 394 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer { 395 return unsafe.Pointer(uintptr(p) + x) 396 } 397 398 // TypeOf returns the reflection Type that represents the dynamic type of i. 399 // If i is a nil interface value, TypeOf returns nil. 400 func TypeOf(i any) Type { 401 eface := *(*emptyInterface)(unsafe.Pointer(&i)) 402 // Noescape so this doesn't make i to escape. See the comment 403 // at Value.typ for why this is safe. 404 return toType((*abi.Type)(noescape(unsafe.Pointer(eface.typ)))) 405 } 406 407 func (t rtype) Implements(u Type) bool { 408 if u == nil { 409 panic("reflect: nil type passed to Type.Implements") 410 } 411 if u.Kind() != Interface { 412 panic("reflect: non-interface type passed to Type.Implements") 413 } 414 return implements(u.common(), t.common()) 415 } 416 417 func (t rtype) AssignableTo(u Type) bool { 418 if u == nil { 419 panic("reflect: nil type passed to Type.AssignableTo") 420 } 421 uu := u.common() 422 tt := t.common() 423 return directlyAssignable(uu, tt) || implements(uu, tt) 424 } 425 426 func (t rtype) Comparable() bool { 427 return t.Equal != nil 428 } 429 430 // implements reports whether the type V implements the interface type T. 431 func implements(T, V *abi.Type) bool { 432 t := T.InterfaceType() 433 if t == nil { 434 return false 435 } 436 if len(t.Methods) == 0 { 437 return true 438 } 439 rT := toRType(T) 440 rV := toRType(V) 441 442 // The same algorithm applies in both cases, but the 443 // method tables for an interface type and a concrete type 444 // are different, so the code is duplicated. 445 // In both cases the algorithm is a linear scan over the two 446 // lists - T's methods and V's methods - simultaneously. 447 // Since method tables are stored in a unique sorted order 448 // (alphabetical, with no duplicate method names), the scan 449 // through V's methods must hit a match for each of T's 450 // methods along the way, or else V does not implement T. 451 // This lets us run the scan in overall linear time instead of 452 // the quadratic time a naive search would require. 453 // See also ../runtime/iface.go. 454 if V.Kind() == Interface { 455 v := (*interfaceType)(unsafe.Pointer(V)) 456 i := 0 457 for j := 0; j < len(v.Methods); j++ { 458 tm := &t.Methods[i] 459 tmName := rT.nameOff(tm.Name) 460 vm := &v.Methods[j] 461 vmName := rV.nameOff(vm.Name) 462 if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) { 463 if !tmName.IsExported() { 464 tmPkgPath := pkgPath(tmName) 465 if tmPkgPath == "" { 466 tmPkgPath = t.PkgPath.Name() 467 } 468 vmPkgPath := pkgPath(vmName) 469 if vmPkgPath == "" { 470 vmPkgPath = v.PkgPath.Name() 471 } 472 if tmPkgPath != vmPkgPath { 473 continue 474 } 475 } 476 if i++; i >= len(t.Methods) { 477 return true 478 } 479 } 480 } 481 return false 482 } 483 484 v := V.Uncommon() 485 if v == nil { 486 return false 487 } 488 i := 0 489 vmethods := v.Methods() 490 for j := 0; j < int(v.Mcount); j++ { 491 tm := &t.Methods[i] 492 tmName := rT.nameOff(tm.Name) 493 vm := vmethods[j] 494 vmName := rV.nameOff(vm.Name) 495 if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) { 496 if !tmName.IsExported() { 497 tmPkgPath := pkgPath(tmName) 498 if tmPkgPath == "" { 499 tmPkgPath = t.PkgPath.Name() 500 } 501 vmPkgPath := pkgPath(vmName) 502 if vmPkgPath == "" { 503 vmPkgPath = rV.nameOff(v.PkgPath).Name() 504 } 505 if tmPkgPath != vmPkgPath { 506 continue 507 } 508 } 509 if i++; i >= len(t.Methods) { 510 return true 511 } 512 } 513 } 514 return false 515 } 516 517 // directlyAssignable reports whether a value x of type V can be directly 518 // assigned (using memmove) to a value of type T. 519 // https://golang.org/doc/go_spec.html#Assignability 520 // Ignoring the interface rules (implemented elsewhere) 521 // and the ideal constant rules (no ideal constants at run time). 522 func directlyAssignable(T, V *abi.Type) bool { 523 // x's type V is identical to T? 524 if T == V { 525 return true 526 } 527 528 // Otherwise at least one of T and V must not be defined 529 // and they must have the same kind. 530 if T.HasName() && V.HasName() || T.Kind() != V.Kind() { 531 return false 532 } 533 534 // x's type T and V must have identical underlying types. 535 return haveIdenticalUnderlyingType(T, V, true) 536 } 537 538 func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool { 539 if cmpTags { 540 return T == V 541 } 542 543 if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() { 544 return false 545 } 546 547 return haveIdenticalUnderlyingType(T, V, false) 548 } 549 550 func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool { 551 if T == V { 552 return true 553 } 554 555 kind := T.Kind() 556 if kind != V.Kind() { 557 return false 558 } 559 560 // Non-composite types of equal kind have same underlying type 561 // (the predefined instance of the type). 562 if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer { 563 return true 564 } 565 566 // Composite types. 567 switch kind { 568 case abi.Array: 569 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 570 571 case abi.Chan: 572 // Special case: 573 // x is a bidirectional channel value, T is a channel type, 574 // and x's type V and T have identical element types. 575 if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) { 576 return true 577 } 578 579 // Otherwise continue test for identical underlying type. 580 return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 581 582 case abi.Func: 583 t := (*funcType)(unsafe.Pointer(T)) 584 v := (*funcType)(unsafe.Pointer(V)) 585 if t.OutCount != v.OutCount || t.InCount != v.InCount { 586 return false 587 } 588 for i := 0; i < t.NumIn(); i++ { 589 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) { 590 return false 591 } 592 } 593 for i := 0; i < t.NumOut(); i++ { 594 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) { 595 return false 596 } 597 } 598 return true 599 600 case Interface: 601 t := (*interfaceType)(unsafe.Pointer(T)) 602 v := (*interfaceType)(unsafe.Pointer(V)) 603 if len(t.Methods) == 0 && len(v.Methods) == 0 { 604 return true 605 } 606 // Might have the same methods but still 607 // need a run time conversion. 608 return false 609 610 case abi.Map: 611 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 612 613 case Ptr, abi.Slice: 614 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags) 615 616 case abi.Struct: 617 t := (*structType)(unsafe.Pointer(T)) 618 v := (*structType)(unsafe.Pointer(V)) 619 if len(t.Fields) != len(v.Fields) { 620 return false 621 } 622 if t.PkgPath.Name() != v.PkgPath.Name() { 623 return false 624 } 625 for i := range t.Fields { 626 tf := &t.Fields[i] 627 vf := &v.Fields[i] 628 if tf.Name.Name() != vf.Name.Name() { 629 return false 630 } 631 if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) { 632 return false 633 } 634 if cmpTags && tf.Name.Tag() != vf.Name.Tag() { 635 return false 636 } 637 if tf.Offset != vf.Offset { 638 return false 639 } 640 if tf.Embedded() != vf.Embedded() { 641 return false 642 } 643 } 644 return true 645 } 646 647 return false 648 } 649 650 // toType converts from a *rtype to a Type that can be returned 651 // to the client of package reflect. In gc, the only concern is that 652 // a nil *rtype must be replaced by a nil Type, but in gccgo this 653 // function takes care of ensuring that multiple *rtype for the same 654 // type are coalesced into a single Type. 655 func toType(t *abi.Type) Type { 656 if t == nil { 657 return nil 658 } 659 return toRType(t) 660 } 661 662 // ifaceIndir reports whether t is stored indirectly in an interface value. 663 func ifaceIndir(t *abi.Type) bool { 664 return t.Kind_&abi.KindDirectIface == 0 665 }