Skip to main content

core/
field.rs

1//! Field Reflection
2
3use crate::marker::PhantomData;
4
5/// Field Representing Type
6#[unstable(feature = "field_representing_type_raw", issue = "none")]
7#[lang = "field_representing_type"]
8#[expect(missing_debug_implementations)]
9#[fundamental]
10pub struct FieldRepresentingType<T: ?Sized, const VARIANT: u32, const FIELD: u32> {
11    // We want this type to be invariant over `T`, because otherwise `field_of!(Struct<'short>,
12    // field)` is a subtype of `field_of!(Struct<'long>, field)`. This subtype relationship does not
13    // have an immediately obvious meaning and we want to prevent people from relying on it.
14    _phantom: PhantomData<fn(T) -> T>,
15}
16
17// SAFETY: `FieldRepresentingType` doesn't contain any `T`
18unsafe impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Send
19    for FieldRepresentingType<T, VARIANT, FIELD>
20{
21}
22
23// SAFETY: `FieldRepresentingType` doesn't contain any `T`
24unsafe impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Sync
25    for FieldRepresentingType<T, VARIANT, FIELD>
26{
27}
28
29impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Copy
30    for FieldRepresentingType<T, VARIANT, FIELD>
31{
32}
33
34impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Clone
35    for FieldRepresentingType<T, VARIANT, FIELD>
36{
37    fn clone(&self) -> Self {
38        *self
39    }
40}
41
42/// Expands to the field representing type of the given field.
43///
44/// The container type may be a tuple, `struct`, `union` or `enum`. In the case of an enum, the
45/// variant must also be specified. Only a single field is supported.
46#[unstable(feature = "field_projections", issue = "145383")]
47#[allow_internal_unstable(field_representing_type_raw, builtin_syntax)]
48// NOTE: when stabilizing this macro, we can never add new trait impls for `FieldRepresentingType`,
49// since it is `#[fundamental]` and thus could break users of this macro, since the compiler expands
50// it to `FieldRepresentingType<...>`. Thus stabilizing this requires careful thought about the
51// completeness of the trait impls for `FieldRepresentingType`.
52pub macro field_of($Container:ty, $($fields:expr)+ $(,)?) {
53    builtin # field_of($Container, $($fields)+)
54}
55
56/// Type representing a field of a `struct`, `union`, `enum` variant or tuple.
57///
58/// # Safety
59///
60/// Given a valid value of type `Self::Base`, there exists a valid value of type `Self::Type` at
61/// byte offset `OFFSET`
62#[lang = "field"]
63#[unstable(feature = "field_projections", issue = "145383")]
64#[rustc_deny_explicit_impl]
65#[rustc_dyn_incompatible_trait]
66// NOTE: the compiler provides the impl of `Field` for `FieldRepresentingType` when it can guarantee
67// the safety requirements of this trait. It also has to manually add the correct trait bounds on
68// associated types (and the `Self` type). Thus any changes to the bounds here must be reflected in
69// the old and new trait solver:
70// - `fn assemble_candidates_for_field_trait` in
71//   `compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs`, and
72// - `fn consider_builtin_field_candidate` in
73//   `compiler/rustc_next_trait_solver/src/solve/trait_goals.rs`.
74pub unsafe trait Field: Send + Sync + Copy {
75    /// The type of the base where this field exists in.
76    #[lang = "field_base"]
77    type Base;
78
79    /// The type of the field.
80    #[lang = "field_type"]
81    type Type;
82
83    /// The offset of the field in bytes.
84    #[lang = "field_offset"]
85    const OFFSET: usize = crate::intrinsics::field_offset::<Self>();
86}