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