diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2025-04-01 11:29:46 +0200 |
|---|---|---|
| committer | Lukas Wirth <me@lukaswirth.dev> | 2025-06-17 10:42:38 +0200 |
| commit | 8e86b84cd16388f7fac3b712fee66637c22182c6 (patch) | |
| tree | 79d930dd5614b3d0edf31c18fdcbdde65fe27954 /src/tools/rust-analyzer/crates/stdx | |
| parent | 69886cfe8a2d67660e61790952c6a00ceec69846 (diff) | |
| download | rust-8e86b84cd16388f7fac3b712fee66637c22182c6.tar.gz rust-8e86b84cd16388f7fac3b712fee66637c22182c6.zip | |
chore: Start infesting ide crates with 'db lifetime
Diffstat (limited to 'src/tools/rust-analyzer/crates/stdx')
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/lib.rs | 1 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/stdx/src/variance.rs | 270 |
2 files changed, 271 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index 9a292eacd7f..978c50d807b 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -13,6 +13,7 @@ pub mod panic_context; pub mod process; pub mod rand; pub mod thread; +pub mod variance; pub use itertools; diff --git a/src/tools/rust-analyzer/crates/stdx/src/variance.rs b/src/tools/rust-analyzer/crates/stdx/src/variance.rs new file mode 100644 index 00000000000..8465d72bf37 --- /dev/null +++ b/src/tools/rust-analyzer/crates/stdx/src/variance.rs @@ -0,0 +1,270 @@ +//! This is a copy of [`std::marker::variance`]. + +use std::any::type_name; +use std::cmp::Ordering; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; + +macro_rules! first_token { + ($first:tt $($rest:tt)*) => { + $first + }; +} +macro_rules! phantom_type { + ($( + $(#[$attr:meta])* + pub struct $name:ident <$t:ident> ($($inner:tt)*); + )*) => {$( + $(#[$attr])* + pub struct $name<$t>($($inner)*) where T: ?Sized; + + impl<T> $name<T> + where T: ?Sized + { + /// Constructs a new instance of the variance marker. + pub const fn new() -> Self { + Self(PhantomData) + } + } + + impl<T> self::sealed::Sealed for $name<T> where T: ?Sized { + const VALUE: Self = Self::new(); + } + + impl<T> Variance for $name<T> where T: ?Sized {} + + impl<T> Default for $name<T> + where T: ?Sized + { + fn default() -> Self { + Self(PhantomData) + } + } + + impl<T> fmt::Debug for $name<T> + where T: ?Sized + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}<{}>", stringify!($name), type_name::<T>()) + } + } + + impl<T> Clone for $name<T> + where T: ?Sized + { + fn clone(&self) -> Self { + *self + } + } + + impl<T> Copy for $name<T> where T: ?Sized {} + + impl<T> PartialEq for $name<T> + where T: ?Sized + { + fn eq(&self, _: &Self) -> bool { + true + } + } + + impl<T> Eq for $name<T> where T: ?Sized {} + + #[allow(clippy::non_canonical_partial_ord_impl)] + impl<T> PartialOrd for $name<T> + where T: ?Sized + { + fn partial_cmp(&self, _: &Self) -> Option<Ordering> { + Some(Ordering::Equal) + } + } + + impl<T> Ord for $name<T> + where T: ?Sized + { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Equal + } + } + + impl<T> Hash for $name<T> + where T: ?Sized + { + fn hash<H: Hasher>(&self, _: &mut H) {} + } + )*}; +} + +macro_rules! phantom_lifetime { + ($( + $(#[$attr:meta])* + pub struct $name:ident <$lt:lifetime> ($($inner:tt)*); + )*) => {$( + $(#[$attr])* + + #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $name<$lt>($($inner)*); + + impl $name<'_> { + /// Constructs a new instance of the variance marker. + pub const fn new() -> Self { + Self(first_token!($($inner)*)(PhantomData)) + } + } + + impl self::sealed::Sealed for $name<'_> { + const VALUE: Self = Self::new(); + } + + impl Variance for $name<'_> {} + + impl fmt::Debug for $name<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", stringify!($name)) + } + } + )*}; +} + +phantom_lifetime! { + /// Zero-sized type used to mark a lifetime as covariant. + /// + /// Covariant lifetimes must live at least as long as declared. See [the reference][1] for more + /// information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::<PhantomCovariantLifetime<'a>>() == 0` + /// * `align_of::<PhantomCovariantLifetime<'a>>() == 1` + + pub struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>); + /// Zero-sized type used to mark a lifetime as contravariant. + /// + /// Contravariant lifetimes must live at most as long as declared. See [the reference][1] for + /// more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::<PhantomContravariantLifetime<'a>>() == 0` + /// * `align_of::<PhantomContravariantLifetime<'a>>() == 1` + + pub struct PhantomContravariantLifetime<'a>(PhantomContravariant<&'a ()>); + /// Zero-sized type used to mark a lifetime as invariant. + /// + /// Invariant lifetimes must be live for the exact length declared, neither shorter nor longer. + /// See [the reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::<PhantomInvariantLifetime<'a>>() == 0` + /// * `align_of::<PhantomInvariantLifetime<'a>>() == 1` + + pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>); + +} + +phantom_type! { + /// Zero-sized type used to mark a type parameter as covariant. + /// + /// Types used as part of the return value from a function are covariant. If the type is _also_ + /// passed as a parameter then it is [invariant][PhantomInvariant]. See [the reference][1] for + /// more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::<PhantomCovariant<T>>() == 0` + /// * `align_of::<PhantomCovariant<T>>() == 1` + + pub struct PhantomCovariant<T>(PhantomData<fn() -> T>); + /// Zero-sized type used to mark a type parameter as contravariant. + /// + /// Types passed as arguments to a function are contravariant. If the type is _also_ part of the + /// return value from a function then it is [invariant][PhantomInvariant]. See [the + /// reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::<PhantomContravariant<T>>() == 0` + /// * `align_of::<PhantomContravariant<T>>() == 1` + + pub struct PhantomContravariant<T>(PhantomData<fn(T)>); + /// Zero-sized type used to mark a type parameter as invariant. + /// + /// Types that are both passed as an argument _and_ used as part of the return value from a + /// function are invariant. See [the reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::<PhantomInvariant<T>>() == 0` + /// * `align_of::<PhantomInvariant<T>>() == 1` + + pub struct PhantomInvariant<T>(PhantomData<fn(T) -> T>); + +} + +mod sealed { + + pub trait Sealed { + const VALUE: Self; + } +} +/// A marker trait for phantom variance types. +pub trait Variance: sealed::Sealed + Default {} +/// Construct a variance marker; equivalent to [`Default::default`]. +/// +/// This type can be any of the following. You generally should not need to explicitly name the +/// type, however. +/// +/// - [`PhantomCovariant`] +/// - [`PhantomContravariant`] +/// - [`PhantomInvariant`] +/// - [`PhantomCovariantLifetime`] +/// - [`PhantomContravariantLifetime`] +/// - [`PhantomInvariantLifetime`] +/// +/// # Example +/// +/// ```rust +/// #![feature(phantom_variance_markers)] +/// +/// use core::marker::{PhantomCovariant, variance}; +/// +/// struct BoundFn<F, P, R> +/// where +/// F: Fn(P) -> R, +/// { +/// function: F, +/// parameter: P, +/// return_value: PhantomCovariant<R>, +/// } +/// +/// let bound_fn = BoundFn { +/// function: core::convert::identity, +/// parameter: 5u8, +/// return_value: variance(), +/// }; +/// ``` +pub const fn variance<T>() -> T +where + T: Variance, +{ + T::VALUE +} |
