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}