Skip to main content

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}