1use crate::fmt;
4use crate::hash::{Hash, Hasher};
5use crate::marker::PhantomData;
6
7#[unstable(feature = "field_representing_type_raw", issue = "none")]
9#[lang = "field_representing_type"]
10#[fundamental]
11pub struct FieldRepresentingType<T: ?Sized, const VARIANT: u32, const FIELD: u32> {
12 _phantom: PhantomData<fn(T) -> T>,
16}
17
18impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> fmt::Debug
19 for FieldRepresentingType<T, VARIANT, FIELD>
20{
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 enum Member {
23 Name(&'static str),
24 Index(u32),
25 }
26 impl fmt::Display for Member {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 Self::Name(name) => fmt::Display::fmt(name, f),
30 Self::Index(idx) => fmt::Display::fmt(idx, f),
31 }
32 }
33 }
34 let (variant, field) = const {
35 use crate::mem::type_info::{Type, TypeKind};
36 match Type::of::<T>().kind {
37 TypeKind::Struct(struct_) => {
38 (None, Member::Name(struct_.fields[FIELD as usize].name))
39 }
40 TypeKind::Tuple(_) => (None, Member::Index(FIELD)),
41 TypeKind::Enum(enum_) => {
42 let variant = &enum_.variants[VARIANT as usize];
43 (Some(variant.name), Member::Name(variant.fields[FIELD as usize].name))
44 }
45 TypeKind::Union(union) => (None, Member::Name(union.fields[FIELD as usize].name)),
46 _ => unreachable!(),
47 }
48 };
49 let type_name = const { crate::any::type_name::<T>() };
50 match variant {
51 Some(variant) => write!(f, "field_of!({type_name}, {variant}.{field})"),
52 None => write!(f, "field_of!({type_name}, {field})"),
53 }
54 }
62}
63
64impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Copy
65 for FieldRepresentingType<T, VARIANT, FIELD>
66{
67}
68
69impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Clone
70 for FieldRepresentingType<T, VARIANT, FIELD>
71{
72 fn clone(&self) -> Self {
73 *self
74 }
75}
76
77impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Default
78 for FieldRepresentingType<T, VARIANT, FIELD>
79{
80 fn default() -> Self {
81 Self { _phantom: PhantomData::default() }
82 }
83}
84
85impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Hash
86 for FieldRepresentingType<T, VARIANT, FIELD>
87{
88 fn hash<H: Hasher>(&self, state: &mut H) {
89 self._phantom.hash(state);
90 }
91}
92
93impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> PartialEq
94 for FieldRepresentingType<T, VARIANT, FIELD>
95{
96 fn eq(&self, other: &Self) -> bool {
97 self._phantom == other._phantom
98 }
99}
100
101impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Eq
102 for FieldRepresentingType<T, VARIANT, FIELD>
103{
104}
105
106impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> PartialOrd
107 for FieldRepresentingType<T, VARIANT, FIELD>
108{
109 fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
110 self._phantom.partial_cmp(&other._phantom)
111 }
112}
113
114impl<T: ?Sized, const VARIANT: u32, const FIELD: u32> Ord
115 for FieldRepresentingType<T, VARIANT, FIELD>
116{
117 fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
118 self._phantom.cmp(&other._phantom)
119 }
120}
121
122#[unstable(feature = "field_projections", issue = "145383")]
127#[allow_internal_unstable(field_representing_type_raw, builtin_syntax)]
128#[diagnostic::on_unmatch_args(
129 note = "this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)`"
130)]
131pub macro field_of($Container:ty, $($fields:expr)+ $(,)?) {
136 builtin # field_of($Container, $($fields)+)
137}
138
139#[lang = "field"]
146#[unstable(feature = "field_projections", issue = "145383")]
147#[rustc_deny_explicit_impl]
148#[rustc_dyn_incompatible_trait]
149pub unsafe trait Field: Send + Sync + Copy {
158 #[lang = "field_base"]
160 type Base;
161
162 #[lang = "field_type"]
164 type Type;
165
166 #[lang = "field_offset"]
168 const OFFSET: usize = crate::intrinsics::field_offset::<Self>();
169}