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}