variance.rs - source
Description: Source of the Rust file `library/core/src/marker/variance.rs`.

#
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}