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