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