core/mem/type_info.rs
1//! MVP for exposing compile-time information about types in a
2//! runtime or const-eval processable way.
3
4use crate::any::TypeId;
5use crate::fmt;
6use crate::intrinsics::{self, type_id, type_of};
7use crate::marker::PointeeSized;
8use crate::ptr::DynMetadata;
9
10/// Compile-time type information.
11#[derive(Debug)]
12#[non_exhaustive]
13#[lang = "type_info"]
14#[unstable(feature = "type_info", issue = "146922")]
15pub struct Type {
16 /// Per-type information
17 pub kind: TypeKind,
18}
19
20/// Info of a trait implementation, you can retrieve the vtable with [Self::get_vtable]
21#[derive(Debug, PartialEq, Eq)]
22#[unstable(feature = "type_info", issue = "146922")]
23pub struct TraitImpl<T: PointeeSized> {
24 pub(crate) vtable: DynMetadata<T>,
25}
26
27impl<T: PointeeSized> TraitImpl<T> {
28 /// Gets the raw vtable for type reflection mapping
29 pub const fn get_vtable(&self) -> DynMetadata<T> {
30 self.vtable
31 }
32}
33
34impl TypeId {
35 /// Compute the type information of a concrete type.
36 /// It can only be called at compile time.
37 #[unstable(feature = "type_info", issue = "146922")]
38 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
39 #[rustc_comptime]
40 pub fn info(self) -> Type {
41 type_of(self)
42 }
43}
44
45impl Type {
46 /// Returns the type information of the generic type parameter.
47 ///
48 /// Note: Unlike `TypeId`s obtained via `TypeId::of`, the `Type`
49 /// struct and its fields contain `TypeId`s that are not necessarily
50 /// derived from types that outlive `'static`. This means that using
51 /// the `TypeId`s (transitively) obtained from this function will
52 /// be able to break invariants that other `TypeId` consuming crates
53 /// may have assumed to hold.
54 #[unstable(feature = "type_info", issue = "146922")]
55 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
56 pub const fn of<T: ?Sized>() -> Self {
57 const { type_id::<T>().info() }
58 }
59}
60
61// FIXME(reflection): get rid of the static lifetime bound on TypeId and remove this function.
62/// Returns the [TypeId] of the generic type parameter.
63///
64/// This is identical to [TypeId::of] but without the static lifetime bound. It will be removed
65/// in the future.
66#[must_use]
67#[unstable(feature = "type_info", issue = "146922")]
68#[rustc_const_unstable(feature = "type_info", issue = "146922")]
69pub const fn of<T: ?Sized>() -> TypeId {
70 const { intrinsics::type_id::<T>() }
71}
72
73/// Compile-time type information.
74#[derive(Debug)]
75#[non_exhaustive]
76#[unstable(feature = "type_info", issue = "146922")]
77pub enum TypeKind {
78 /// Tuples.
79 Tuple,
80 /// Arrays.
81 Array(Array),
82 /// Slices.
83 Slice(Slice),
84 /// Dynamic Traits.
85 DynTrait(DynTrait),
86 /// Structs.
87 Struct,
88 /// Enums.
89 Enum,
90 /// Unions.
91 Union,
92 /// Primitive boolean type.
93 Bool(Bool),
94 /// Primitive character type.
95 Char(Char),
96 /// Primitive signed and unsigned integer type.
97 Int(Int),
98 /// Primitive floating-point type.
99 Float(Float),
100 /// String slice type.
101 Str(Str),
102 /// References.
103 Reference(Reference),
104 /// Pointers.
105 Pointer(Pointer),
106 /// Function pointers.
107 FnPtr(FnPtr),
108 /// FIXME(#146922): add all the common types
109 Other,
110}
111
112/// Compile-time type information about arrays.
113#[derive(Debug)]
114#[non_exhaustive]
115#[unstable(feature = "type_info", issue = "146922")]
116pub struct Array {
117 /// The type of each element in the array.
118 pub element_ty: TypeId,
119 /// The length of the array.
120 pub len: usize,
121}
122
123/// Compile-time type information about slices.
124#[derive(Debug)]
125#[non_exhaustive]
126#[unstable(feature = "type_info", issue = "146922")]
127pub struct Slice {
128 /// The type of each element in the slice.
129 pub element_ty: TypeId,
130}
131
132/// Compile-time type information about dynamic traits.
133/// FIXME(#146922): Add super traits and generics
134#[derive(Debug)]
135#[non_exhaustive]
136#[unstable(feature = "type_info", issue = "146922")]
137pub struct DynTrait {
138 /// The predicates of a dynamic trait.
139 pub predicates: &'static [DynTraitPredicate],
140}
141
142/// Compile-time type information about a dynamic trait predicate.
143#[derive(Debug)]
144#[non_exhaustive]
145#[unstable(feature = "type_info", issue = "146922")]
146pub struct DynTraitPredicate {
147 /// The type of the trait as a dynamic trait type.
148 pub trait_ty: Trait,
149}
150
151/// Compile-time type information about a trait.
152#[derive(Debug)]
153#[non_exhaustive]
154#[unstable(feature = "type_info", issue = "146922")]
155pub struct Trait {
156 /// The TypeId of the trait as a dynamic type
157 pub ty: TypeId,
158 /// Whether the trait is an auto trait
159 pub is_auto: bool,
160}
161
162/// Compile-time type information about instantiated generics of structs, enum and union variants.
163#[derive(Debug)]
164#[non_exhaustive]
165#[unstable(feature = "type_info", issue = "146922")]
166#[lang = "type_info_generic"]
167pub enum Generic {
168 /// Lifetimes.
169 Lifetime(Lifetime),
170 /// Types.
171 Type(GenericType),
172 /// Const parameters.
173 Const(Const),
174}
175
176/// Compile-time type information about generic lifetimes.
177#[derive(Debug)]
178#[non_exhaustive]
179#[unstable(feature = "type_info", issue = "146922")]
180pub struct Lifetime {
181 // No additional information to provide for now.
182}
183
184/// Compile-time type information about instantiated generic types.
185#[derive(Debug)]
186#[non_exhaustive]
187#[unstable(feature = "type_info", issue = "146922")]
188pub struct GenericType {
189 /// The type itself.
190 pub ty: TypeId,
191}
192
193/// Compile-time type information about generic const parameters.
194#[derive(Debug)]
195#[non_exhaustive]
196#[unstable(feature = "type_info", issue = "146922")]
197pub struct Const {
198 /// The const's type.
199 pub ty: TypeId,
200}
201
202/// Compile-time type information about `bool`.
203#[derive(Debug)]
204#[non_exhaustive]
205#[unstable(feature = "type_info", issue = "146922")]
206pub struct Bool {
207 // No additional information to provide for now.
208}
209
210/// Compile-time type information about `char`.
211#[derive(Debug)]
212#[non_exhaustive]
213#[unstable(feature = "type_info", issue = "146922")]
214pub struct Char {
215 // No additional information to provide for now.
216}
217
218/// Compile-time type information about signed and unsigned integer types.
219#[derive(Debug)]
220#[non_exhaustive]
221#[unstable(feature = "type_info", issue = "146922")]
222pub struct Int {
223 /// The bit width of the signed integer type.
224 pub bits: u32,
225 /// Whether the integer type is signed.
226 pub signed: bool,
227}
228
229/// Compile-time type information about floating-point types.
230#[derive(Debug)]
231#[non_exhaustive]
232#[unstable(feature = "type_info", issue = "146922")]
233pub struct Float {
234 /// The bit width of the floating-point type.
235 pub bits: u32,
236}
237
238/// Compile-time type information about string slice types.
239#[derive(Debug)]
240#[non_exhaustive]
241#[unstable(feature = "type_info", issue = "146922")]
242pub struct Str {
243 // No additional information to provide for now.
244}
245
246/// Compile-time type information about references.
247#[derive(Debug)]
248#[non_exhaustive]
249#[unstable(feature = "type_info", issue = "146922")]
250pub struct Reference {
251 /// The type of the value being referred to.
252 pub pointee: TypeId,
253 /// Whether this reference is mutable or not.
254 pub mutable: bool,
255}
256
257/// Compile-time type information about pointers.
258#[derive(Debug)]
259#[non_exhaustive]
260#[unstable(feature = "type_info", issue = "146922")]
261pub struct Pointer {
262 /// The type of the value being pointed to.
263 pub pointee: TypeId,
264 /// Whether this pointer is mutable or not.
265 pub mutable: bool,
266}
267
268#[derive(Debug)]
269#[unstable(feature = "type_info", issue = "146922")]
270/// Function pointer, e.g. fn(u8),
271pub struct FnPtr {
272 /// Unsafety, true is unsafe
273 pub unsafety: bool,
274
275 /// Abi, e.g. extern "C"
276 pub abi: Abi,
277
278 /// Function inputs
279 pub inputs: &'static [TypeId],
280
281 /// Function return type, default is TypeId::of::<()>
282 pub output: TypeId,
283
284 /// Vardiadic function, e.g. extern "C" fn add(n: usize, mut args: ...);
285 pub variadic: bool,
286
287 // FIXME(splat): should these fields be private, or merged into an Option<u8/u16>?
288 /// Is any function argument splatted?
289 pub is_splatted: bool,
290
291 /// The index of the splatted function argument in `inputs`, only valid if `is_splatted` is true.
292 /// e.g. in `fn overload(a: u8, #[rustc_splat] b: (f32, usize))` the index is 1, and it can be called
293 /// as `overload(a, 1.0, 2)`.
294 pub splatted_index: u8,
295}
296
297impl FnPtr {
298 /// Returns the splatted function argument index, or `None` if no argument is splatted.
299 pub const fn splatted(&self) -> Option<u8> {
300 if self.is_splatted { Some(self.splatted_index) } else { None }
301 }
302}
303
304#[derive(Debug, Default)]
305#[non_exhaustive]
306#[unstable(feature = "type_info", issue = "146922")]
307/// Abi of [FnPtr]
308pub enum Abi {
309 /// Named abi, e.g. extern "custom", "stdcall" etc.
310 Named(&'static str),
311
312 /// Default
313 #[default]
314 ExternRust,
315
316 /// C-calling convention
317 ExternC,
318}
319
320impl TypeId {
321 /// Returns `true` if the type represented by this `TypeId` is an signed integer.
322 ///
323 /// For everything else this returns false.
324 ///
325 /// # Examples
326 ///
327 /// ```
328 /// #![feature(type_info)]
329 /// use std::any::TypeId;
330 ///
331 /// assert_eq!(const { TypeId::of::<i32>().is_signed() }, true);
332 /// assert_eq!(const { TypeId::of::<u8>().is_signed() }, false);
333 /// assert_eq!(const { TypeId::of::<bool>().is_signed() }, false);
334 /// ```
335 #[unstable(feature = "type_info", issue = "146922")]
336 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
337 #[rustc_comptime]
338 pub fn is_signed(self) -> bool {
339 intrinsics::type_id_is_signed(self)
340 }
341
342 /// Returns the size of the type represented by this `TypeId`. `None` if it is unsized.
343 ///
344 /// # Examples
345 ///
346 /// ```
347 /// #![feature(type_info)]
348 /// use std::any::TypeId;
349 ///
350 /// assert_eq!(const { TypeId::of::<u32>().size() }, Some(4));
351 /// assert_eq!(const { TypeId::of::<[u8; 16]>().size() }, Some(16));
352 /// ```
353 #[unstable(feature = "type_info", issue = "146922")]
354 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
355 #[rustc_comptime]
356 pub fn size(self) -> Option<usize> {
357 intrinsics::size_of_type_id(self)
358 }
359
360 /// Returns the number of variants of the type represented by this `TypeId`.
361 ///
362 /// For enums, this is the number of variants. For structs and unions, this is always 1.
363 ///
364 /// ```
365 /// #![feature(type_info)]
366 /// use std::any::TypeId;
367 ///
368 /// assert_eq!(const { TypeId::of::<Option<()>>().variants() }, 2);
369 ///
370 /// struct Unit;
371 /// struct Point {
372 /// x: u32,
373 /// y: u32,
374 /// }
375 /// assert_eq!(const { TypeId::of::<Unit>().variants() }, 1);
376 /// assert_eq!(const { TypeId::of::<Point>().variants() }, 1);
377 /// assert_eq!(const { TypeId::of::<(f32, f32)>().variants() }, 1);
378 /// ```
379 #[unstable(feature = "type_info", issue = "146922")]
380 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
381 #[rustc_comptime]
382 pub fn variants(self) -> usize {
383 intrinsics::type_id_variants(self)
384 }
385
386 // FIXME(reflection): make the errors nicer. This is a wider problem,
387 // TypeId::fields has nice errors in the docs but those are not the ones shown
388 // by rustc.
389 /// Returns the variant representing type at the given index of the type represented by this `TypeId`. Use it to
390 /// get the name of an enum variant or check whether it is non_exhaustive.
391 ///
392 /// ```
393 /// #![feature(type_info)]
394 /// use std::any::TypeId;
395 ///
396 /// enum Enum {
397 /// Unit,
398 /// Tuple(u32, u64),
399 /// #[non_exhaustive]
400 /// Struct { x: u32, y: u32, z: String },
401 /// }
402 /// assert_eq!(const { TypeId::of::<Enum>().variant(1).name() }, "Tuple");
403 /// assert_eq!(const { TypeId::of::<Enum>().variant(2).name() }, "Struct");
404 ///
405 /// assert_eq!(const { TypeId::of::<Enum>().variant(1).non_exhaustive() }, false);
406 /// assert_eq!(const { TypeId::of::<Enum>().variant(2).non_exhaustive() }, true);
407 /// ```
408 ///
409 /// The variant index refer to the source order index of a variant in a type.
410 ///
411 /// Variant indexes are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
412 ///
413 /// ```
414 /// enum Enum {
415 /// Foo, // variant index == 0
416 /// Bar, // variant index == 1
417 /// }
418 /// ```
419 ///
420 /// Calling variant on the TypeId for a struct will be treated as a compile-time error. The same
421 /// is true for out-of-bounds indexing on an enum.
422 ///
423 /// ```compile_fail,E0080
424 /// # #![feature(type_info)]
425 /// # use std::any::TypeId;
426 /// #
427 /// # struct Point {
428 /// # x: u32,
429 /// # y: u32,
430 /// # }
431 /// # enum Enum {
432 /// # Unit,
433 /// # Tuple(u32, u64),
434 /// # Struct { x: u32, y: u32, z: String },
435 /// # }
436 /// const {
437 /// _ = TypeId::of::<Point>().variant(0); // error: cannot get the variant of a struct
438 /// _ = TypeId::of::<Enum>().variant(10); // error: indexing out of bounds: the len is 3 but the index is 10
439 /// }
440 /// ```
441 #[unstable(feature = "type_info", issue = "146922")]
442 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
443 #[rustc_comptime]
444 pub fn variant(self, variant_index: usize) -> VariantId {
445 intrinsics::type_id_fields(self, variant_index);
446 VariantId { base: self, variant: variant_index }
447 }
448
449 /// Returns the number of fields at the given `variant_index` of the type represented by this `TypeId`.
450 ///
451 /// ```
452 /// #![feature(type_info)]
453 /// use std::any::TypeId;
454 ///
455 /// assert_eq!(const { TypeId::of::<u32>().fields(0) }, 0);
456 ///
457 /// struct Point {
458 /// x: u32,
459 /// y: u32,
460 /// }
461 /// assert_eq!(const { TypeId::of::<Point>().fields(0) }, 2);
462 ///
463 /// enum Enum {
464 /// Unit,
465 /// Tuple(u32, u64),
466 /// Struct { x: u32, y: u32, z: String },
467 /// }
468 /// assert_eq!(const { TypeId::of::<Enum>().fields(0) }, 0);
469 /// assert_eq!(const { TypeId::of::<Enum>().fields(1) }, 2);
470 /// assert_eq!(const { TypeId::of::<Enum>().fields(2) }, 3);
471 /// ```
472 ///
473 /// The variant index refers to the source order index of a variant in a type.
474 ///
475 /// For enums, these are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
476 /// `struct`s, `tuples`, and `unions`s are considered to have a single variant with variant index zero.
477 ///
478 /// ```
479 /// enum Number {
480 /// Seven = 7, // variant index == 0
481 /// Six = 6, // variant index == 1
482 /// }
483 /// ```
484 ///
485 /// Out-of-bounds indexing will be treated as a compile-time error.
486 ///
487 /// ```compile_fail,E0080
488 /// # #![feature(type_info)]
489 /// # use std::any::TypeId;
490 /// #
491 /// # struct Point {
492 /// # x: u32,
493 /// # y: u32,
494 /// # }
495 /// # enum Enum {
496 /// # Unit,
497 /// # Tuple(u32, u64),
498 /// # Struct { x: u32, y: u32, z: String },
499 /// # }
500 /// const {
501 /// _ = TypeId::of::<Point>().fields(10); // error: indexing out of bounds: the len is 2 but the index is 10
502 /// _ = TypeId::of::<Enum>().fields(10); // error: indexing out of bounds: the len is 3 but the index is 10
503 /// }
504 /// ```
505 #[unstable(feature = "type_info", issue = "146922")]
506 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
507 #[rustc_comptime]
508 // FIXME(type_info): Add enum variant pattern types and use them to represent individual variants
509 // Then add a `variant` method to get a wrapper around such a pattern type (similar to the FRT
510 // type we have) and add methods on that. It's the only way to really sensibly represent
511 // things like `non_exhaustive` which can be applied to variants as well.
512 pub fn fields(self, variant_index: usize) -> usize {
513 intrinsics::type_id_fields(self, variant_index)
514 }
515
516 /// Returns the field representing type at the given index of the type represented by this `TypeId`.
517 ///
518 /// ```
519 /// #![feature(type_info)]
520 /// use std::any::TypeId;
521 ///
522 /// struct Point {
523 /// x: u32,
524 /// y: u32,
525 /// }
526 /// assert_eq!(const { TypeId::of::<Point>().field(0, 0).type_id() }, TypeId::of::<u32>());
527 /// assert_eq!(const { TypeId::of::<Point>().field(0, 1).type_id() }, TypeId::of::<u32>());
528 ///
529 /// enum Enum {
530 /// Unit,
531 /// Tuple(u32, u64),
532 /// Struct { x: u32, y: u32, z: String },
533 /// }
534 /// assert_eq!(const { TypeId::of::<Enum>().field(1, 0).type_id() }, TypeId::of::<u32>());
535 /// assert_eq!(const { TypeId::of::<Enum>().field(2, 2).type_id() }, TypeId::of::<String>());
536 /// ```
537 ///
538 /// The variant index and field index refer to the source order index of a variant in a type and
539 /// the source order index of a field in a variant, respectively.
540 ///
541 /// For enums, variant indexes are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
542 /// `struct`s, `tuples`, and `unions`s are considered to have a single variant with variant index zero.
543 ///
544 /// As for field indexes, they may not be the same as the layout order for `repr(Rust)` types, but they are for `repr(C)` types.
545 ///
546 /// ```
547 /// enum Enum {
548 /// Foo, // variant index == 0
549 /// Bar { // variant index == 1
550 /// a: (), // field index == 0 in `Bar`
551 /// b: (), // field index == 1 in `Bar`
552 /// }
553 /// }
554 /// ```
555 ///
556 /// Out-of-bounds indexing will be treated as a compile-time error.
557 ///
558 /// ```compile_fail,E0080
559 /// # #![feature(type_info)]
560 /// # use std::any::TypeId;
561 /// #
562 /// # struct Point {
563 /// # x: u32,
564 /// # y: u32,
565 /// # }
566 /// # enum Enum {
567 /// # Unit,
568 /// # Tuple(u32, u64),
569 /// # Struct { x: u32, y: u32, z: String },
570 /// # }
571 /// const {
572 /// _ = TypeId::of::<Point>().field(0, 10); // error: indexing out of bounds: the len is 2 but the index is 10
573 /// _ = TypeId::of::<Enum>().field(2, 10); // error: indexing out of bounds: the len is 3 but the index is 10
574 /// }
575 /// ```
576 #[unstable(feature = "type_info", issue = "146922")]
577 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
578 #[rustc_comptime]
579 pub fn field(self, variant_index: usize, field_index: usize) -> FieldId {
580 FieldId {
581 frt_type_id: intrinsics::type_id_field_representing_type(
582 self,
583 variant_index,
584 field_index,
585 ),
586 }
587 }
588
589 /// Returns whether a type is marked with `#[non_exhaustive]`.
590 /// Returns `false` for everything but adts.
591 #[unstable(feature = "type_info", issue = "146922")]
592 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
593 #[rustc_comptime]
594 pub fn non_exhaustive(self) -> bool {
595 intrinsics::non_exhaustive(self)
596 }
597
598 /// Returns a list of generic parameters of the type.
599 /// Returns an empty slice for everything that doesn't have generics.
600 #[unstable(feature = "type_info", issue = "146922")]
601 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
602 #[rustc_comptime]
603 pub fn generics(self) -> &'static [Generic] {
604 intrinsics::type_id_generics(self)
605 }
606}
607
608/// Variant representing type ID. Representing a variant of an enum.
609#[derive(Copy, PartialOrd, Ord, Hash)]
610#[derive_const(Clone, PartialEq, Eq)]
611#[unstable(feature = "type_info", issue = "146922")]
612pub struct VariantId {
613 base: TypeId,
614 variant: usize,
615}
616
617#[unstable(feature = "type_info", issue = "146922")]
618impl fmt::Debug for VariantId {
619 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
620 write!(f, "Variant({:#034x}-{})", self.base.as_u128(), self.variant)
621 }
622}
623
624impl VariantId {
625 /// Returns the name of the variant.
626 ///
627 /// ```
628 /// #![feature(type_info)]
629 /// use std::any::TypeId;
630 ///
631 /// enum Enum {
632 /// Unit,
633 /// Tuple(bool),
634 /// Struct { a: bool },
635 /// }
636 /// assert_eq!(
637 /// const { TypeId::of::<Enum>().variant(1).name() },
638 /// "Tuple",
639 /// );
640 /// ```
641 #[unstable(feature = "type_info", issue = "146922")]
642 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
643 #[rustc_comptime]
644 pub fn name(self) -> &'static str {
645 intrinsics::variant_name(self.base, self.variant)
646 }
647
648 /// Returns whether this variant is marked with `#[non_exhaustive]`.
649 #[unstable(feature = "type_info", issue = "146922")]
650 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
651 #[rustc_comptime]
652 pub fn non_exhaustive(self) -> bool {
653 intrinsics::variant_non_exhaustive(self.base, self.variant)
654 }
655}
656
657/// Field representing type ID. Representing a field of a struct, tuple or enum variant.
658#[derive(Copy, PartialOrd, Ord, Hash)]
659#[derive_const(Clone, PartialEq, Eq)]
660#[unstable(feature = "type_info", issue = "146922")]
661pub struct FieldId {
662 frt_type_id: TypeId,
663}
664
665#[unstable(feature = "type_info", issue = "146922")]
666impl fmt::Debug for FieldId {
667 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668 write!(f, "FieldId({:#034x})", self.frt_type_id.as_u128())
669 }
670}
671
672impl FieldId {
673 /// Returns the `TypeId` of the actual field type.
674 ///
675 /// ```
676 /// #![feature(type_info)]
677 /// use std::any::TypeId;
678 ///
679 /// struct Point {
680 /// x: u32,
681 /// y: u32,
682 /// }
683 /// assert_eq!(
684 /// const { TypeId::of::<Point>().field(0, 0).type_id() },
685 /// TypeId::of::<u32>()
686 /// );
687 /// ```
688 #[unstable(feature = "type_info", issue = "146922")]
689 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
690 #[rustc_comptime]
691 pub fn type_id(self) -> TypeId {
692 intrinsics::field_representing_type_actual_type_id(self.frt_type_id)
693 }
694
695 /// Returns the name of the field.
696 ///
697 /// ```
698 /// #![feature(type_info)]
699 /// use std::any::TypeId;
700 ///
701 /// struct Point {
702 /// x: u32,
703 /// y: u32,
704 /// }
705 /// assert_eq!(
706 /// const { TypeId::of::<Point>().field(0, 0).name() },
707 /// "x",
708 /// );
709 /// ```
710 #[unstable(feature = "type_info", issue = "146922")]
711 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
712 #[rustc_comptime]
713 pub fn name(self) -> &'static str {
714 intrinsics::field_representing_type_name(self.frt_type_id)
715 }
716 /// Returns the offset of the field wrt to its containing type.
717 ///
718 /// ```
719 /// #![feature(type_info)]
720 /// use std::any::TypeId;
721 ///
722 /// #[repr(C)]
723 /// struct Point {
724 /// x: u32,
725 /// y: u32,
726 /// }
727 /// assert_eq!(
728 /// const { TypeId::of::<Point>().field(0, 1).offset() },
729 /// 4,
730 /// );
731 /// ```
732 #[unstable(feature = "type_info", issue = "146922")]
733 #[rustc_const_unstable(feature = "type_info", issue = "146922")]
734 #[rustc_comptime]
735 pub fn offset(self) -> usize {
736 intrinsics::field_representing_type_offset(self.frt_type_id)
737 }
738}