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::intrinsics::{self, type_id, type_of};
6use crate::marker::PointeeSized;
7use crate::ptr::DynMetadata;
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")]
22#[non_exhaustive]
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    pub const fn info(self) -> Type {
40        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 { type_id::<T>().info() }
57    }
58}
59
60/// Compile-time type information.
61#[derive(Debug)]
62#[non_exhaustive]
63#[unstable(feature = "type_info", issue = "146922")]
64pub enum TypeKind {
65    /// Tuples.
66    Tuple(Tuple),
67    /// Arrays.
68    Array(Array),
69    /// Slices.
70    Slice(Slice),
71    /// Dynamic Traits.
72    DynTrait(DynTrait),
73    /// Structs.
74    Struct(Struct),
75    /// Enums.
76    Enum(Enum),
77    /// Unions.
78    Union(Union),
79    /// Primitive boolean type.
80    Bool(Bool),
81    /// Primitive character type.
82    Char(Char),
83    /// Primitive signed and unsigned integer type.
84    Int(Int),
85    /// Primitive floating-point type.
86    Float(Float),
87    /// String slice type.
88    Str(Str),
89    /// References.
90    Reference(Reference),
91    /// Pointers.
92    Pointer(Pointer),
93    /// Function pointers.
94    FnPtr(FnPtr),
95    /// FIXME(#146922): add all the common types
96    Other,
97}
98
99/// Compile-time type information about tuples.
100#[derive(Debug)]
101#[non_exhaustive]
102#[unstable(feature = "type_info", issue = "146922")]
103pub struct Tuple {
104    /// All fields of a tuple.
105    pub fields: &'static [Field],
106}
107
108/// Compile-time type information about fields of tuples, structs and enum variants.
109#[derive(Debug)]
110#[non_exhaustive]
111#[unstable(feature = "type_info", issue = "146922")]
112pub struct Field {
113    /// The name of the field.
114    pub name: &'static str,
115    /// The field's type.
116    pub ty: TypeId,
117    /// Offset in bytes from the parent type
118    pub offset: usize,
119}
120
121/// Compile-time type information about arrays.
122#[derive(Debug)]
123#[non_exhaustive]
124#[unstable(feature = "type_info", issue = "146922")]
125pub struct Array {
126    /// The type of each element in the array.
127    pub element_ty: TypeId,
128    /// The length of the array.
129    pub len: usize,
130}
131
132/// Compile-time type information about slices.
133#[derive(Debug)]
134#[non_exhaustive]
135#[unstable(feature = "type_info", issue = "146922")]
136pub struct Slice {
137    /// The type of each element in the slice.
138    pub element_ty: TypeId,
139}
140
141/// Compile-time type information about dynamic traits.
142/// FIXME(#146922): Add super traits and generics
143#[derive(Debug)]
144#[non_exhaustive]
145#[unstable(feature = "type_info", issue = "146922")]
146pub struct DynTrait {
147    /// The predicates of  a dynamic trait.
148    pub predicates: &'static [DynTraitPredicate],
149}
150
151/// Compile-time type information about a dynamic trait predicate.
152#[derive(Debug)]
153#[non_exhaustive]
154#[unstable(feature = "type_info", issue = "146922")]
155pub struct DynTraitPredicate {
156    /// The type of the trait as a dynamic trait type.
157    pub trait_ty: Trait,
158}
159
160/// Compile-time type information about a trait.
161#[derive(Debug)]
162#[non_exhaustive]
163#[unstable(feature = "type_info", issue = "146922")]
164pub struct Trait {
165    /// The TypeId of the trait as a dynamic type
166    pub ty: TypeId,
167    /// Whether the trait is an auto trait
168    pub is_auto: bool,
169}
170
171/// Compile-time type information about structs.
172#[derive(Debug)]
173#[non_exhaustive]
174#[unstable(feature = "type_info", issue = "146922")]
175pub struct Struct {
176    /// Instantiated generics of the struct.
177    pub generics: &'static [Generic],
178    /// All fields of the struct.
179    pub fields: &'static [Field],
180    /// Whether the struct field list is non-exhaustive.
181    pub non_exhaustive: bool,
182}
183
184/// Compile-time type information about unions.
185#[derive(Debug)]
186#[non_exhaustive]
187#[unstable(feature = "type_info", issue = "146922")]
188pub struct Union {
189    /// Instantiated generics of the union.
190    pub generics: &'static [Generic],
191    /// All fields of the union.
192    pub fields: &'static [Field],
193}
194
195/// Compile-time type information about enums.
196#[derive(Debug)]
197#[non_exhaustive]
198#[unstable(feature = "type_info", issue = "146922")]
199pub struct Enum {
200    /// Instantiated generics of the enum.
201    pub generics: &'static [Generic],
202    /// All variants of the enum.
203    pub variants: &'static [Variant],
204    /// Whether the enum variant list is non-exhaustive.
205    pub non_exhaustive: bool,
206}
207
208/// Compile-time type information about variants of enums.
209#[derive(Debug)]
210#[non_exhaustive]
211#[unstable(feature = "type_info", issue = "146922")]
212pub struct Variant {
213    /// The name of the variant.
214    pub name: &'static str,
215    /// All fields of the variant.
216    pub fields: &'static [Field],
217    /// Whether the enum variant fields is non-exhaustive.
218    pub non_exhaustive: bool,
219}
220
221/// Compile-time type information about instantiated generics of structs, enum and union variants.
222#[derive(Debug)]
223#[non_exhaustive]
224#[unstable(feature = "type_info", issue = "146922")]
225pub enum Generic {
226    /// Lifetimes.
227    Lifetime(Lifetime),
228    /// Types.
229    Type(GenericType),
230    /// Const parameters.
231    Const(Const),
232}
233
234/// Compile-time type information about generic lifetimes.
235#[derive(Debug)]
236#[non_exhaustive]
237#[unstable(feature = "type_info", issue = "146922")]
238pub struct Lifetime {
239    // No additional information to provide for now.
240}
241
242/// Compile-time type information about instantiated generic types.
243#[derive(Debug)]
244#[non_exhaustive]
245#[unstable(feature = "type_info", issue = "146922")]
246pub struct GenericType {
247    /// The type itself.
248    pub ty: TypeId,
249}
250
251/// Compile-time type information about generic const parameters.
252#[derive(Debug)]
253#[non_exhaustive]
254#[unstable(feature = "type_info", issue = "146922")]
255pub struct Const {
256    /// The const's type.
257    pub ty: TypeId,
258}
259
260/// Compile-time type information about `bool`.
261#[derive(Debug)]
262#[non_exhaustive]
263#[unstable(feature = "type_info", issue = "146922")]
264pub struct Bool {
265    // No additional information to provide for now.
266}
267
268/// Compile-time type information about `char`.
269#[derive(Debug)]
270#[non_exhaustive]
271#[unstable(feature = "type_info", issue = "146922")]
272pub struct Char {
273    // No additional information to provide for now.
274}
275
276/// Compile-time type information about signed and unsigned integer types.
277#[derive(Debug)]
278#[non_exhaustive]
279#[unstable(feature = "type_info", issue = "146922")]
280pub struct Int {
281    /// The bit width of the signed integer type.
282    pub bits: u32,
283    /// Whether the integer type is signed.
284    pub signed: bool,
285}
286
287/// Compile-time type information about floating-point types.
288#[derive(Debug)]
289#[non_exhaustive]
290#[unstable(feature = "type_info", issue = "146922")]
291pub struct Float {
292    /// The bit width of the floating-point type.
293    pub bits: u32,
294}
295
296/// Compile-time type information about string slice types.
297#[derive(Debug)]
298#[non_exhaustive]
299#[unstable(feature = "type_info", issue = "146922")]
300pub struct Str {
301    // No additional information to provide for now.
302}
303
304/// Compile-time type information about references.
305#[derive(Debug)]
306#[non_exhaustive]
307#[unstable(feature = "type_info", issue = "146922")]
308pub struct Reference {
309    /// The type of the value being referred to.
310    pub pointee: TypeId,
311    /// Whether this reference is mutable or not.
312    pub mutable: bool,
313}
314
315/// Compile-time type information about pointers.
316#[derive(Debug)]
317#[non_exhaustive]
318#[unstable(feature = "type_info", issue = "146922")]
319pub struct Pointer {
320    /// The type of the value being pointed to.
321    pub pointee: TypeId,
322    /// Whether this pointer is mutable or not.
323    pub mutable: bool,
324}
325
326#[derive(Debug)]
327#[unstable(feature = "type_info", issue = "146922")]
328/// Function pointer, e.g. fn(u8),
329pub struct FnPtr {
330    /// Unsafety, true is unsafe
331    pub unsafety: bool,
332
333    /// Abi, e.g. extern "C"
334    pub abi: Abi,
335
336    /// Function inputs
337    pub inputs: &'static [TypeId],
338
339    /// Function return type, default is TypeId::of::<()>
340    pub output: TypeId,
341
342    /// Vardiadic function, e.g. extern "C" fn add(n: usize, mut args: ...);
343    pub variadic: bool,
344}
345
346#[derive(Debug, Default)]
347#[non_exhaustive]
348#[unstable(feature = "type_info", issue = "146922")]
349/// Abi of [FnPtr]
350pub enum Abi {
351    /// Named abi, e.g. extern "custom", "stdcall" etc.
352    Named(&'static str),
353
354    /// Default
355    #[default]
356    ExternRust,
357
358    /// C-calling convention
359    ExternC,
360}
361
362impl TypeId {
363    /// Returns the size of the type represented by this `TypeId`. `None` if it is unsized.
364    ///
365    /// # Examples
366    ///
367    /// ```
368    /// #![feature(type_info)]
369    /// use std::any::TypeId;
370    ///
371    /// assert_eq!(const { TypeId::of::<u32>().size() }, Some(4));
372    /// assert_eq!(const { TypeId::of::<[u8; 16]>().size() }, Some(16));
373    /// ```
374    #[unstable(feature = "type_info", issue = "146922")]
375    #[rustc_const_unstable(feature = "type_info", issue = "146922")]
376    pub const fn size(self) -> Option<usize> {
377        intrinsics::size_of_type_id(self)
378    }
379}