core/marker/variance.rs
1#![unstable(feature = "phantom_variance_markers", issue = "135806")]
2
3use super::PhantomData;
4use crate::any::type_name;
5use crate::clone::TrivialClone;
6use crate::cmp::Ordering;
7use crate::fmt;
8use crate::hash::{Hash, Hasher};
9
10macro_rules! first_token {
11 ($first:tt $($rest:tt)*) => {
12 $first
13 };
14}
15
16macro_rules! phantom_type {
17 ($(
18 $(#[$attr:meta])*
19 pub struct $name:ident <$t:ident> ($($inner:tt)*);
20 )*) => {$(
21 $(#[$attr])*
22 pub struct $name<$t>($($inner)*) where $t: ?Sized;
23
24 impl<T> $name<T>
25 where T: ?Sized
26 {
27 /// Constructs a new instance of the variance marker.
28 pub const fn new() -> Self {
29 Self(PhantomData)
30 }
31 }
32
33 impl<T> self::sealed::Sealed for $name<T> where T: ?Sized {
34 const VALUE: Self = Self::new();
35 }
36 impl<T> Variance for $name<T> where T: ?Sized {}
37
38 impl<T> Default for $name<T>
39 where T: ?Sized
40 {
41 fn default() -> Self {
42 Self(PhantomData)
43 }
44 }
45
46 impl<T> fmt::Debug for $name<T>
47 where T: ?Sized
48 {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(f, "{}<{}>", stringify!($name), type_name::<T>())
51 }
52 }
53
54 impl<T> Clone for $name<T>
55 where T: ?Sized
56 {
57 fn clone(&self) -> Self {
58 *self
59 }
60 }
61
62 impl<T> Copy for $name<T> where T: ?Sized {}
63
64 #[doc(hidden)]
65 unsafe impl<T> TrivialClone for $name<T> where T: ?Sized {}
66
67 impl<T> PartialEq for $name<T>
68 where T: ?Sized
69 {
70 fn eq(&self, _: &Self) -> bool {
71 true
72 }
73 }
74
75 impl<T> Eq for $name<T> where T: ?Sized {}
76
77 impl<T> PartialOrd for $name<T>
78 where T: ?Sized
79 {
80 fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
81 Some(Ordering::Equal)
82 }
83 }
84
85 impl<T> Ord for $name<T>
86 where T: ?Sized
87 {
88 fn cmp(&self, _: &Self) -> Ordering {
89 Ordering::Equal
90 }
91 }
92
93 impl<T> Hash for $name<T>
94 where T: ?Sized
95 {
96 fn hash<H: Hasher>(&self, _: &mut H) {}
97 }
98 )*};
99}
100
101macro_rules! phantom_lifetime {
102 ($(
103 $(#[$attr:meta])*
104 pub struct $name:ident <$lt:lifetime> ($($inner:tt)*);
105 )*) => {$(
106 $(#[$attr])*
107 #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
108 pub struct $name<$lt>($($inner)*);
109
110 impl $name<'_> {
111 /// Constructs a new instance of the variance marker.
112 pub const fn new() -> Self {
113 Self(first_token!($($inner)*)(PhantomData))
114 }
115 }
116
117 impl self::sealed::Sealed for $name<'_> {
118 const VALUE: Self = Self::new();
119 }
120 impl Variance for $name<'_> {}
121
122 impl fmt::Debug for $name<'_> {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(f, "{}", stringify!($name))
125 }
126 }
127 )*};
128}
129
130phantom_lifetime! {
131 /// Zero-sized type used to mark a lifetime as covariant.
132 ///
133 /// Covariant lifetimes must live at least as long as declared. See [the reference][1] for more
134 /// information.
135 ///
136 /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
137 ///
138 /// Note: If `'a` is otherwise contravariant or invariant, the resulting type is invariant.
139 ///
140 /// ## Layout
141 ///
142 /// For all `'a`, the following are guaranteed:
143 /// * `size_of::<PhantomCovariantLifetime<'a>>() == 0`
144 /// * `align_of::<PhantomCovariantLifetime<'a>>() == 1`
145 #[rustc_pub_transparent]
146 #[repr(transparent)]
147 pub struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>);
148 /// Zero-sized type used to mark a lifetime as contravariant.
149 ///
150 /// Contravariant lifetimes must live at most as long as declared. See [the reference][1] for
151 /// more information.
152 ///
153 /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
154 ///
155 /// Note: If `'a` is otherwise covariant or invariant, the resulting type is invariant.
156 ///
157 /// ## Layout
158 ///
159 /// For all `'a`, the following are guaranteed:
160 /// * `size_of::<PhantomContravariantLifetime<'a>>() == 0`
161 /// * `align_of::<PhantomContravariantLifetime<'a>>() == 1`
162 #[rustc_pub_transparent]
163 #[repr(transparent)]
164 pub struct PhantomContravariantLifetime<'a>(PhantomContravariant<&'a ()>);
165 /// Zero-sized type used to mark a lifetime as invariant.
166 ///
167 /// Invariant lifetimes must be live for the exact length declared, neither shorter nor longer.
168 /// See [the reference][1] for more information.
169 ///
170 /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
171 ///
172 /// ## Layout
173 ///
174 /// For all `'a`, the following are guaranteed:
175 /// * `size_of::<PhantomInvariantLifetime<'a>>() == 0`
176 /// * `align_of::<PhantomInvariantLifetime<'a>>() == 1`
177 #[rustc_pub_transparent]
178 #[repr(transparent)]
179 pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>);
180}
181
182phantom_type! {
183 /// Zero-sized type used to mark a type parameter as covariant.
184 ///
185 /// Types used as part of the return value from a function are covariant. If the type is _also_
186 /// passed as a parameter then it is [invariant][PhantomInvariant]. See [the reference][1] for
187 /// more information.
188 ///
189 /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
190 ///
191 /// Note: If `T` is otherwise contravariant or invariant, the resulting type is invariant.
192 ///
193 /// ## Layout
194 ///
195 /// For all `T`, the following are guaranteed:
196 /// * `size_of::<PhantomCovariant<T>>() == 0`
197 /// * `align_of::<PhantomCovariant<T>>() == 1`
198 #[rustc_pub_transparent]
199 #[repr(transparent)]
200 pub struct PhantomCovariant<T>(PhantomData<fn() -> T>);
201 /// Zero-sized type used to mark a type parameter as contravariant.
202 ///
203 /// Types passed as arguments to a function are contravariant. If the type is _also_ part of the
204 /// return value from a function then it is [invariant][PhantomInvariant]. See [the
205 /// reference][1] for more information.
206 ///
207 /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
208 ///
209 /// Note: If `T` is otherwise covariant or invariant, the resulting type is invariant.
210 ///
211 /// ## Layout
212 ///
213 /// For all `T`, the following are guaranteed:
214 /// * `size_of::<PhantomContravariant<T>>() == 0`
215 /// * `align_of::<PhantomContravariant<T>>() == 1`
216 #[rustc_pub_transparent]
217 #[repr(transparent)]
218 pub struct PhantomContravariant<T>(PhantomData<fn(T)>);
219 /// Zero-sized type used to mark a type parameter as invariant.
220 ///
221 /// Types that are both passed as an argument _and_ used as part of the return value from a
222 /// function are invariant. See [the reference][1] for more information.
223 ///
224 /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
225 ///
226 /// ## Layout
227 ///
228 /// For all `T`, the following are guaranteed:
229 /// * `size_of::<PhantomInvariant<T>>() == 0`
230 /// * `align_of::<PhantomInvariant<T>>() == 1`
231 #[rustc_pub_transparent]
232 #[repr(transparent)]
233 pub struct PhantomInvariant<T>(PhantomData<fn(T) -> T>);
234}
235
236mod sealed {
237 pub trait Sealed {
238 const VALUE: Self;
239 }
240}
241
242/// A marker trait for phantom variance types.
243pub trait Variance: sealed::Sealed + Default {}
244
245/// Construct a variance marker; equivalent to [`Default::default`].
246///
247/// This type can be any of the following. You generally should not need to explicitly name the
248/// type, however.
249///
250/// - [`PhantomCovariant`]
251/// - [`PhantomContravariant`]
252/// - [`PhantomInvariant`]
253/// - [`PhantomCovariantLifetime`]
254/// - [`PhantomContravariantLifetime`]
255/// - [`PhantomInvariantLifetime`]
256///
257/// # Example
258///
259/// ```rust
260/// #![feature(phantom_variance_markers)]
261///
262/// use core::marker::{PhantomCovariant, variance};
263///
264/// struct BoundFn<F, P, R>
265/// where
266/// F: Fn(P) -> R,
267/// {
268/// function: F,
269/// parameter: P,
270/// return_value: PhantomCovariant<R>,
271/// }
272///
273/// let bound_fn = BoundFn {
274/// function: core::convert::identity,
275/// parameter: 5u8,
276/// return_value: variance(),
277/// };
278/// ```
279pub const fn variance<T>() -> T
280where
281 T: Variance,
282{
283 T::VALUE
284}