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}