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,
82    /// Slices.
83    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,
94    /// Primitive character type.
95    Char,
96    /// Primitive signed and unsigned integer type.
97    Int,
98    /// Primitive floating-point type.
99    Float,
100    /// String slice type.
101    Str(Str),
102    /// References.
103    Reference,
104    /// Pointers.
105    Pointer,
106    /// Function pointers.
107    FnPtr,
108    /// FIXME(#146922): add all the common types
109    /// non exhaustive list:
110    /// - Never
111    Other,
112}
113
114/// Compile-time type information about dynamic traits.
115/// FIXME(#146922): Add super traits and generics
116#[derive(Debug)]
117#[non_exhaustive]
118#[unstable(feature = "type_info", issue = "146922")]
119pub struct DynTrait {
120    /// The predicates of  a dynamic trait.
121    pub predicates: &'static [DynTraitPredicate],
122}
123
124/// Compile-time type information about a dynamic trait predicate.
125#[derive(Debug)]
126#[non_exhaustive]
127#[unstable(feature = "type_info", issue = "146922")]
128pub struct DynTraitPredicate {
129    /// The type of the trait as a dynamic trait type.
130    pub trait_ty: Trait,
131}
132
133/// Compile-time type information about a trait.
134#[derive(Debug)]
135#[non_exhaustive]
136#[unstable(feature = "type_info", issue = "146922")]
137pub struct Trait {
138    /// The TypeId of the trait as a dynamic type
139    pub ty: TypeId,
140    /// Whether the trait is an auto trait
141    pub is_auto: bool,
142}
143
144/// Compile-time type information about instantiated generics of structs, enum and union variants.
145#[derive(Debug)]
146#[non_exhaustive]
147#[unstable(feature = "type_info", issue = "146922")]
148#[lang = "type_info_generic"]
149pub enum Generic {
150    /// Lifetimes.
151    Lifetime(Lifetime),
152    /// Types.
153    Type(GenericType),
154    /// Const parameters.
155    Const(Const),
156}
157
158/// Compile-time type information about generic lifetimes.
159#[derive(Debug)]
160#[non_exhaustive]
161#[unstable(feature = "type_info", issue = "146922")]
162pub struct Lifetime {
163    // No additional information to provide for now.
164}
165
166/// Compile-time type information about instantiated generic types.
167#[derive(Debug)]
168#[non_exhaustive]
169#[unstable(feature = "type_info", issue = "146922")]
170pub struct GenericType {
171    /// The type itself.
172    pub ty: TypeId,
173}
174
175/// Compile-time type information about generic const parameters.
176#[derive(Debug)]
177#[non_exhaustive]
178#[unstable(feature = "type_info", issue = "146922")]
179pub struct Const {
180    /// The const's type.
181    pub ty: TypeId,
182}
183
184/// Compile-time type information about string slice types.
185#[derive(Debug)]
186#[non_exhaustive]
187#[unstable(feature = "type_info", issue = "146922")]
188pub struct Str {
189    // No additional information to provide for now.
190}
191
192#[derive(Debug)]
193#[lang = "FnPtr"]
194#[unstable(feature = "type_info", issue = "146922")]
195/// Function pointer, e.g. fn(u8),
196pub struct FnPtr {
197    is_unsafe: bool,
198    abi: Abi,
199    inputs: &'static [TypeId],
200    output: TypeId,
201    variadic: bool,
202    // FIXME(splat): should these fields be private, or merged into an Option<u8/u16>?
203    /// Is any function argument splatted?
204    is_splatted: bool,
205
206    splatted_index: u8,
207}
208
209impl FnPtr {
210    /// Returns the splatted function argument index, or `None` if no argument is splatted.
211    ///
212    /// e.g. in `fn overload(a: u8, #[rustc_splat] b: (f32, usize))` the index is 1,
213    /// and it can be called as `overload(a, 1.0, 2)`.
214    pub const fn splatted(&self) -> Option<u8> {
215        if self.is_splatted { Some(self.splatted_index) } else { None }
216    }
217    /// Whether this function is variadic, e.g. extern "C" fn add(n: usize, mut args: ...);
218    pub const fn is_variadic(&self) -> bool {
219        self.variadic
220    }
221    /// whether this refers to an unsafe function.
222    pub const fn is_unsafe(&self) -> bool {
223        self.is_unsafe
224    }
225    /// Returns the application binary interface. For example extern "C".
226    pub const fn abi(&self) -> Abi {
227        self.abi
228    }
229    /// The types of the functions parameters
230    pub const fn inputs(&self) -> &'static [TypeId] {
231        self.inputs
232    }
233    /// List of the types returned by the function. For a function with no output
234    /// specified this returns `TypeId::of<()>`.
235    pub const fn output(&self) -> TypeId {
236        self.output
237    }
238}
239
240#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
241#[non_exhaustive]
242#[unstable(feature = "type_info", issue = "146922")]
243/// Abi of [FnPtr]
244pub enum Abi {
245    /// Named abi, e.g. extern "custom", "stdcall" etc.
246    Named(&'static str),
247
248    /// Default
249    #[default]
250    ExternRust,
251
252    /// C-calling convention
253    ExternC,
254}
255
256impl TypeId {
257    /// Returns `true` if the type represented by this `TypeId` is an signed integer.
258    ///
259    /// For everything else this returns false.
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// #![feature(type_info)]
265    /// use std::any::TypeId;
266    ///
267    /// assert_eq!(const { TypeId::of::<i32>().is_signed() }, true);
268    /// assert_eq!(const { TypeId::of::<u8>().is_signed() }, false);
269    /// assert_eq!(const { TypeId::of::<bool>().is_signed() }, false);
270    /// ```
271    #[unstable(feature = "type_info", issue = "146922")]
272    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
273    #[rustc_comptime]
274    pub fn is_signed(self) -> bool {
275        intrinsics::type_id_is_signed(self)
276    }
277
278    /// When called on a `TypeId` representing an array or slice this returns the type of each
279    /// element otherwise this returns `None`.
280    ///
281    /// # Examples
282    ///
283    /// ```
284    /// #![feature(type_info)]
285    /// use std::any::TypeId;
286    ///
287    /// assert_eq!(const { TypeId::of::<[u32; 16]>().element_ty() }, Some(TypeId::of::<u32>()));
288    /// assert_eq!(const { TypeId::of::<u8>().element_ty() }, None); // not an array or slice
289    /// ```
290    #[unstable(feature = "type_info", issue = "146922")]
291    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
292    #[rustc_comptime]
293    pub fn element_ty(self) -> Option<TypeId> {
294        intrinsics::type_id_element_ty(self)
295    }
296
297    /// When called on a `TypeId` representing an array this returns the length of the array in
298    /// all other cases this returns zero.
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// #![feature(type_info)]
304    /// use std::any::TypeId;
305    ///
306    /// assert_eq!(const { TypeId::of::<[u32; 16]>().array_len() }, 16);
307    /// assert_eq!(const { TypeId::of::<u8>().array_len() }, 0); // not an array
308    /// ```
309    #[unstable(feature = "type_info", issue = "146922")]
310    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
311    #[rustc_comptime]
312    pub fn array_len(self) -> usize {
313        intrinsics::type_id_array_len(self)
314    }
315
316    /// Returns the size of the type represented by this `TypeId`. `None` if it is unsized.
317    ///
318    /// # Examples
319    ///
320    /// ```
321    /// #![feature(type_info)]
322    /// use std::any::TypeId;
323    ///
324    /// assert_eq!(const { TypeId::of::<u32>().size() }, Some(4));
325    /// assert_eq!(const { TypeId::of::<[u8; 16]>().size() }, Some(16));
326    /// ```
327    #[unstable(feature = "type_info", issue = "146922")]
328    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
329    #[rustc_comptime]
330    pub fn size(self) -> Option<usize> {
331        intrinsics::size_of_type_id(self)
332    }
333
334    /// Returns the number of variants of the type represented by this `TypeId`.
335    ///
336    /// For enums, this is the number of variants. For structs and unions, this is always 1.
337    ///
338    /// ```
339    /// #![feature(type_info)]
340    /// use std::any::TypeId;
341    ///
342    /// assert_eq!(const { TypeId::of::<Option<()>>().variants() }, 2);
343    ///
344    /// struct Unit;
345    /// struct Point {
346    ///     x: u32,
347    ///     y: u32,
348    /// }
349    /// assert_eq!(const { TypeId::of::<Unit>().variants() }, 1);
350    /// assert_eq!(const { TypeId::of::<Point>().variants() }, 1);
351    /// assert_eq!(const { TypeId::of::<(f32, f32)>().variants() }, 1);
352    /// ```
353    #[unstable(feature = "type_info", issue = "146922")]
354    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
355    #[rustc_comptime]
356    pub fn variants(self) -> usize {
357        intrinsics::type_id_variants(self)
358    }
359
360    // FIXME(reflection): make the errors nicer. This is a wider problem,
361    // TypeId::fields has nice errors in the docs but those are not the ones shown
362    // by rustc.
363    /// Returns the variant representing type at the given index of the type represented by this `TypeId`. Use it to
364    /// get the name of an enum variant or check whether it is non_exhaustive.
365    ///
366    /// ```
367    /// #![feature(type_info)]
368    /// use std::any::TypeId;
369    ///
370    /// enum Enum {
371    ///     Unit,
372    ///     Tuple(u32, u64),
373    ///     #[non_exhaustive]
374    ///     Struct { x: u32, y: u32, z: String },
375    /// }
376    /// assert_eq!(const { TypeId::of::<Enum>().variant(1).name() }, "Tuple");
377    /// assert_eq!(const { TypeId::of::<Enum>().variant(2).name() }, "Struct");
378    ///
379    /// assert_eq!(const { TypeId::of::<Enum>().variant(1).non_exhaustive() }, false);
380    /// assert_eq!(const { TypeId::of::<Enum>().variant(2).non_exhaustive() }, true);
381    /// ```
382    ///
383    /// The variant index refer to the source order index of a variant in a type.
384    ///
385    /// Variant indexes are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
386    ///
387    /// ```
388    /// enum Enum {
389    ///     Foo,  // variant index == 0
390    ///     Bar,  // variant index == 1
391    /// }
392    /// ```
393    ///
394    /// Calling variant on the TypeId for a struct will be treated as a compile-time error. The same
395    /// is true for out-of-bounds indexing on an enum.
396    ///
397    /// ```compile_fail,E0080
398    /// # #![feature(type_info)]
399    /// # use std::any::TypeId;
400    /// #
401    /// # struct Point {
402    /// #     x: u32,
403    /// #     y: u32,
404    /// # }
405    /// # enum Enum {
406    /// #     Unit,
407    /// #     Tuple(u32, u64),
408    /// #     Struct { x: u32, y: u32, z: String },
409    /// # }
410    /// const {
411    ///     _ = TypeId::of::<Point>().variant(0); // error: cannot get the variant of a struct
412    ///     _ = TypeId::of::<Enum>().variant(10); // error: indexing out of bounds: the len is 3 but the index is 10
413    /// }
414    /// ```
415    #[unstable(feature = "type_info", issue = "146922")]
416    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
417    #[rustc_comptime]
418    pub fn variant(self, variant_index: usize) -> VariantId {
419        intrinsics::type_id_fields(self, variant_index);
420        VariantId { base: self, variant: variant_index }
421    }
422
423    /// Returns the number of fields at the given `variant_index` of the type represented by this `TypeId`.
424    ///
425    /// ```
426    /// #![feature(type_info)]
427    /// use std::any::TypeId;
428    ///
429    /// assert_eq!(const { TypeId::of::<u32>().fields(0) }, 0);
430    ///
431    /// struct Point {
432    ///     x: u32,
433    ///     y: u32,
434    /// }
435    /// assert_eq!(const { TypeId::of::<Point>().fields(0) }, 2);
436    ///
437    /// enum Enum {
438    ///     Unit,
439    ///     Tuple(u32, u64),
440    ///     Struct { x: u32, y: u32, z: String },
441    /// }
442    /// assert_eq!(const { TypeId::of::<Enum>().fields(0) }, 0);
443    /// assert_eq!(const { TypeId::of::<Enum>().fields(1) }, 2);
444    /// assert_eq!(const { TypeId::of::<Enum>().fields(2) }, 3);
445    /// ```
446    ///
447    /// The variant index refers to the source order index of a variant in a type.
448    ///
449    /// For enums, these are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
450    /// `struct`s, `tuples`, and `unions`s are considered to have a single variant with variant index zero.
451    ///
452    /// ```
453    /// enum Number {
454    ///     Seven = 7, // variant index == 0
455    ///     Six = 6,   // variant index == 1
456    /// }
457    /// ```
458    ///
459    /// Out-of-bounds indexing will be treated as a compile-time error.
460    ///
461    /// ```compile_fail,E0080
462    /// # #![feature(type_info)]
463    /// # use std::any::TypeId;
464    /// #
465    /// # struct Point {
466    /// #     x: u32,
467    /// #     y: u32,
468    /// # }
469    /// # enum Enum {
470    /// #     Unit,
471    /// #     Tuple(u32, u64),
472    /// #     Struct { x: u32, y: u32, z: String },
473    /// # }
474    /// const {
475    ///     _ = TypeId::of::<Point>().fields(10); // error: indexing out of bounds: the len is 2 but the index is 10
476    ///     _ = TypeId::of::<Enum>().fields(10); // error: indexing out of bounds: the len is 3 but the index is 10
477    /// }
478    /// ```
479    #[unstable(feature = "type_info", issue = "146922")]
480    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
481    #[rustc_comptime]
482    // FIXME(type_info): Add enum variant pattern types and use them to represent individual variants
483    // Then add a `variant` method to get a wrapper around such a pattern type (similar to the FRT
484    // type we have) and add methods on that. It's the only way to really sensibly represent
485    // things like `non_exhaustive` which can be applied to variants as well.
486    pub fn fields(self, variant_index: usize) -> usize {
487        intrinsics::type_id_fields(self, variant_index)
488    }
489
490    /// Returns the field representing type at the given index of the type represented by this `TypeId`.
491    ///
492    /// ```
493    /// #![feature(type_info)]
494    /// use std::any::TypeId;
495    ///
496    /// struct Point {
497    ///     x: u32,
498    ///     y: u32,
499    /// }
500    /// assert_eq!(const { TypeId::of::<Point>().field(0, 0).type_id() }, TypeId::of::<u32>());
501    /// assert_eq!(const { TypeId::of::<Point>().field(0, 1).type_id() }, TypeId::of::<u32>());
502    ///
503    /// enum Enum {
504    ///     Unit,
505    ///     Tuple(u32, u64),
506    ///     Struct { x: u32, y: u32, z: String },
507    /// }
508    /// assert_eq!(const { TypeId::of::<Enum>().field(1, 0).type_id() }, TypeId::of::<u32>());
509    /// assert_eq!(const { TypeId::of::<Enum>().field(2, 2).type_id() }, TypeId::of::<String>());
510    /// ```
511    ///
512    /// The variant index and field index refer to the source order index of a variant in a type and
513    /// the source order index of a field in a variant, respectively.
514    ///
515    /// For enums, variant indexes are always `0..variant_count`, regardless of any custom discriminants that may have been defined.
516    /// `struct`s, `tuples`, and `unions`s are considered to have a single variant with variant index zero.
517    ///
518    /// 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.
519    ///
520    /// ```
521    /// enum Enum {
522    ///     Foo,  // variant index == 0
523    ///     Bar { // variant index == 1
524    ///         a: (), // field index == 0 in `Bar`
525    ///         b: (), // field index == 1 in `Bar`
526    ///     }
527    /// }
528    /// ```
529    ///
530    /// Out-of-bounds indexing will be treated as a compile-time error.
531    ///
532    /// ```compile_fail,E0080
533    /// # #![feature(type_info)]
534    /// # use std::any::TypeId;
535    /// #
536    /// # struct Point {
537    /// #     x: u32,
538    /// #     y: u32,
539    /// # }
540    /// # enum Enum {
541    /// #     Unit,
542    /// #     Tuple(u32, u64),
543    /// #     Struct { x: u32, y: u32, z: String },
544    /// # }
545    /// const {
546    ///     _ = TypeId::of::<Point>().field(0, 10); // error: indexing out of bounds: the len is 2 but the index is 10
547    ///     _ = TypeId::of::<Enum>().field(2, 10); // error: indexing out of bounds: the len is 3 but the index is 10
548    /// }
549    /// ```
550    #[unstable(feature = "type_info", issue = "146922")]
551    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
552    #[rustc_comptime]
553    pub fn field(self, variant_index: usize, field_index: usize) -> FieldId {
554        FieldId {
555            frt_type_id: intrinsics::type_id_field_representing_type(
556                self,
557                variant_index,
558                field_index,
559            ),
560        }
561    }
562
563    /// Returns whether a type is marked with `#[non_exhaustive]`.
564    /// Returns `false` for everything but adts.
565    #[unstable(feature = "type_info", issue = "146922")]
566    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
567    #[rustc_comptime]
568    pub fn non_exhaustive(self) -> bool {
569        intrinsics::non_exhaustive(self)
570    }
571
572    /// Returns a list of generic parameters of the type.
573    /// Returns an empty slice for everything that doesn't have generics.
574    #[unstable(feature = "type_info", issue = "146922")]
575    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
576    #[rustc_comptime]
577    pub fn generics(self) -> &'static [Generic] {
578        intrinsics::type_id_generics(self)
579    }
580
581    /// Given a `TypeId` that represents a pointer this returns the `TypeId`
582    /// which that pointer points to. When called on anything else this returns
583    /// None.
584    ///
585    /// ```
586    /// #![feature(type_info)]
587    /// use std::any::TypeId;
588    ///
589    /// assert_eq!(
590    ///     const { TypeId::of::<&i32>().points_to() },
591    ///     const { Some(TypeId::of::<i32>()) },
592    /// );
593    ///
594    /// assert_eq!(
595    ///     const { TypeId::of::<*const i32>().points_to() },
596    ///     const { Some(TypeId::of::<i32>()) },
597    /// );
598    /// ```
599    #[unstable(feature = "type_info", issue = "146922")]
600    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
601    #[rustc_comptime]
602    pub fn points_to(self) -> Option<TypeId> {
603        intrinsics::type_id_points_to(self)
604    }
605
606    /// Given a `TypeId` that represents a pointer returns whether that pointer is mutable.
607    /// When called on anything else this returns `false`.
608    ///
609    /// ```
610    /// #![feature(type_info)]
611    /// use std::any::TypeId;
612    ///
613    /// assert!(const { TypeId::of::<&mut i32>().points_mutably() });
614    /// assert!(const { !TypeId::of::<&i32>().points_mutably() });
615    ///
616    /// assert!(!const { TypeId::of::<*const i32>().points_mutably() });
617    /// assert!(const { TypeId::of::<*mut i32>().points_mutably() });
618    /// ```
619    #[unstable(feature = "type_info", issue = "146922")]
620    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
621    #[rustc_comptime]
622    pub fn points_mutably(self) -> bool {
623        intrinsics::type_id_points_mutably(self)
624    }
625
626    /// Given a `TypeId` that represents a function pointer returns an
627    /// [`FnPtr`]. When called on something else this returns `None`.
628    /// ```
629    /// #![feature(type_info)]
630    /// use std::any::TypeId;
631    /// use std::mem::type_info::{Abi, FnPtr};
632    ///
633    /// const F: FnPtr = TypeId::of::<fn(u8, u16) -> usize>()
634    ///     .function_ptr()
635    ///     .expect("TypeId of a function ptr");
636    ///
637    /// assert!(F.inputs() == [TypeId::of::<u8>(), TypeId::of::<u16>()]);
638    /// assert!(F.output() == TypeId::of::<usize>());
639    /// assert!(F.abi() == Abi::default());
640    /// ```
641    /// ```
642    /// #![feature(type_info)]
643    /// # use std::any::TypeId;
644    /// # use std::mem::type_info::{Abi, FnPtr};
645    /// #
646    /// const F: FnPtr = TypeId::of::<unsafe fn()>()
647    ///     .function_ptr()
648    ///     .expect("TypeId of a function ptr");
649    ///
650    /// assert!(F.inputs() == []);
651    /// assert!(F.output() == TypeId::of::<()>());
652    /// assert!(F.abi() == Abi::default());
653    /// ```
654    #[unstable(feature = "type_info", issue = "146922")]
655    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
656    #[rustc_comptime]
657    pub fn function_ptr(self) -> Option<FnPtr> {
658        intrinsics::type_id_function_ptr(self)
659    }
660}
661
662/// Variant representing type ID. Representing a variant of an enum.
663#[derive(Copy, PartialOrd, Ord, Hash)]
664#[derive_const(Clone, PartialEq, Eq)]
665#[unstable(feature = "type_info", issue = "146922")]
666pub struct VariantId {
667    base: TypeId,
668    variant: usize,
669}
670
671#[unstable(feature = "type_info", issue = "146922")]
672impl fmt::Debug for VariantId {
673    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
674        write!(f, "Variant({:#034x}-{})", self.base.as_u128(), self.variant)
675    }
676}
677
678impl VariantId {
679    /// Returns the name of the variant.
680    ///
681    /// ```
682    /// #![feature(type_info)]
683    /// use std::any::TypeId;
684    ///
685    /// enum Enum {
686    ///     Unit,
687    ///     Tuple(bool),
688    ///     Struct { a: bool },
689    /// }
690    /// assert_eq!(
691    ///     const { TypeId::of::<Enum>().variant(1).name() },
692    ///     "Tuple",
693    /// );
694    /// ```
695    #[unstable(feature = "type_info", issue = "146922")]
696    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
697    #[rustc_comptime]
698    pub fn name(self) -> &'static str {
699        intrinsics::variant_name(self.base, self.variant)
700    }
701
702    /// Returns whether this variant is marked with `#[non_exhaustive]`.
703    #[unstable(feature = "type_info", issue = "146922")]
704    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
705    #[rustc_comptime]
706    pub fn non_exhaustive(self) -> bool {
707        intrinsics::variant_non_exhaustive(self.base, self.variant)
708    }
709}
710
711/// Field representing type ID. Representing a field of a struct, tuple or enum variant.
712#[derive(Copy, PartialOrd, Ord, Hash)]
713#[derive_const(Clone, PartialEq, Eq)]
714#[unstable(feature = "type_info", issue = "146922")]
715pub struct FieldId {
716    frt_type_id: TypeId,
717}
718
719#[unstable(feature = "type_info", issue = "146922")]
720impl fmt::Debug for FieldId {
721    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722        write!(f, "FieldId({:#034x})", self.frt_type_id.as_u128())
723    }
724}
725
726impl FieldId {
727    /// Returns the `TypeId` of the actual field type.
728    ///
729    /// ```
730    /// #![feature(type_info)]
731    /// use std::any::TypeId;
732    ///
733    /// struct Point {
734    ///     x: u32,
735    ///     y: u32,
736    /// }
737    /// assert_eq!(
738    ///     const { TypeId::of::<Point>().field(0, 0).type_id() },
739    ///     TypeId::of::<u32>()
740    /// );
741    /// ```
742    #[unstable(feature = "type_info", issue = "146922")]
743    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
744    #[rustc_comptime]
745    pub fn type_id(self) -> TypeId {
746        intrinsics::field_representing_type_actual_type_id(self.frt_type_id)
747    }
748
749    /// Returns the name of the field.
750    ///
751    /// ```
752    /// #![feature(type_info)]
753    /// use std::any::TypeId;
754    ///
755    /// struct Point {
756    ///     x: u32,
757    ///     y: u32,
758    /// }
759    /// assert_eq!(
760    ///     const { TypeId::of::<Point>().field(0, 0).name() },
761    ///     "x",
762    /// );
763    /// ```
764    #[unstable(feature = "type_info", issue = "146922")]
765    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
766    #[rustc_comptime]
767    pub fn name(self) -> &'static str {
768        intrinsics::field_representing_type_name(self.frt_type_id)
769    }
770    /// Returns the offset of the field wrt to its containing type.
771    ///
772    /// ```
773    /// #![feature(type_info)]
774    /// use std::any::TypeId;
775    ///
776    /// #[repr(C)]
777    /// struct Point {
778    ///     x: u32,
779    ///     y: u32,
780    /// }
781    /// assert_eq!(
782    ///     const { TypeId::of::<Point>().field(0, 1).offset() },
783    ///     4,
784    /// );
785    /// ```
786    #[unstable(feature = "type_info", issue = "146922")]
787    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
788    #[rustc_comptime]
789    pub fn offset(self) -> usize {
790        intrinsics::field_representing_type_offset(self.frt_type_id)
791    }
792}