[Go to site: main page, start]

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