Thanks to visit codestin.com
Credit goes to doc.rust-lang.org

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}