]>
git.proxmox.com Git - rustc.git/blob - vendor/yoke/src/is_covariant.rs
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
5 #[cfg(feature = "alloc")]
7 borrow
::{Cow, ToOwned}
,
13 /// A type implementing `IsCovariant<'a>` is covariant with respect to lifetime `'a`.
15 /// Lifetime parameters that are safely cast in [`Yokeable`] are also valid for `IsCovariant`.
17 /// `IsCovariant` exists primarily to serve in trait bounds. The primary use case is to safely
18 /// perform lifetime casting on trait objects (`dyn Trait`). This enables a type-erased [`Yoke`]
19 /// consisting of only trait objects. See the examples.
21 /// `IsCovariant` is auto-implemented in [`#[derive(Yokeable)]`](macro@crate::Yokeable).
25 /// This trait is safe to implement on types with a _covariant_ lifetime parameter. This will
26 /// occur when the lifetime parameter is used within references, but not in the arguments of
27 /// function pointers or in mutable positions (either in `&mut` or via interior mutability).
29 /// If a struct has multiple lifetime parameters, only the one used in `IsCovariant<'a>` needs to
34 /// Implementing on a simple struct with a single covariant lifetime:
38 /// struct MyStruct<'a>(&'a str);
40 /// // This is safe because 'a is covariant
41 /// unsafe impl<'a> IsCovariant<'a> for MyStruct<'a> {}
44 /// By constraining the trait `ExampleTrait<'a>` on `IsCovariant<'a>`, we can safely implement
45 /// [`Yokeable`] and [`ZeroFrom`] on its trait object:
49 /// # use zerofrom::*;
51 /// trait ExampleTrait<'a>: IsCovariant<'a> {
52 /// fn get_message(&self) -> &'a str;
55 /// // This wrapper is required because of the blanket Yokeable impl on &'static T
56 /// pub struct ExampleTraitDynRef<'a>(pub &'a dyn ExampleTrait<'a>);
58 /// // The following impl is safe because the trait object requires IsCovariant.
59 /// unsafe impl<'a> Yokeable<'a> for ExampleTraitDynRef<'static> {
60 /// type Output = ExampleTraitDynRef<'a>;
61 /// fn transform(&'a self) -> &'a Self::Output {
62 /// unsafe { mem::transmute(self) }
65 /// fn transform_owned(self) -> Self::Output {
66 /// unsafe { mem::transmute(self) }
69 /// unsafe fn make(from: Self::Output) -> Self {
70 /// unsafe { mem::transmute(from) }
73 /// fn transform_mut<F>(&'a mut self, f: F)
75 /// F: 'static + FnOnce(&'a mut Self::Output),
77 /// unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
81 /// impl<'zf, 'a> ZeroFrom<'zf, dyn ExampleTrait<'a> + 'a> for ExampleTraitDynRef<'zf> {
82 /// fn zero_from(this: &'zf (dyn ExampleTrait<'a> + 'a)) -> ExampleTraitDynRef<'zf> {
83 /// // This is safe because the trait object requires IsCovariant.
84 /// ExampleTraitDynRef(unsafe { core::mem::transmute(this) })
88 /// // Implement ExampleTrait on the struct from the previous example
89 /// # struct MyStruct<'a>(&'a str);
90 /// # unsafe impl<'a> IsCovariant<'a> for MyStruct<'a> {}
91 /// impl<'a> ExampleTrait<'a> for MyStruct<'a> {
92 /// fn get_message(&self) -> &'a str {
97 /// // Example usage: a Yoke of a trait object
98 /// let s = "Hello World".to_string();
99 /// let yoke: Yoke<ExampleTraitDynRef<'static>, Box<dyn ExampleTrait>> =
100 /// Yoke::attach_to_zero_copy_cart(Box::new(MyStruct(&s)));
102 /// assert_eq!(yoke.get().0.get_message(), "Hello World");
105 /// [`Yoke`]: crate::Yoke
106 /// [`Yokeable`]: crate::Yokeable
107 /// [`ZeroFrom`]: crate::ZeroFrom
108 pub unsafe trait IsCovariant
<'a
>: 'a {}
110 // IsCovariant is implemented on the standard library Copy types in macro_impls.rs
112 // The following impls are safe because there is only one lifetime, 'a, and 'a is covariant
114 unsafe impl<'a
> IsCovariant
<'a
> for () {}
116 unsafe impl<'a
> IsCovariant
<'a
> for str {}
117 #[cfg(feature = "alloc")]
118 unsafe impl<'a
> IsCovariant
<'a
> for String {}
120 unsafe impl<'a
, T
: IsCovariant
<'a
>> IsCovariant
<'a
> for Option
<T
> {}
122 unsafe impl<'a
, T1
: IsCovariant
<'a
>, T2
: IsCovariant
<'a
>> IsCovariant
<'a
> for (T1
, T2
) {}
124 unsafe impl<'a
, T
: IsCovariant
<'a
>> IsCovariant
<'a
> for [T
] {}
126 unsafe impl<'a
, T
: IsCovariant
<'a
>, const N
: usize> IsCovariant
<'a
> for [T
; N
] {}
128 #[cfg(feature = "alloc")]
129 unsafe impl<'a
, T
: IsCovariant
<'a
> + ?Sized
> IsCovariant
<'a
> for Box
<T
> {}
131 #[cfg(feature = "alloc")]
132 unsafe impl<'a
, T
: IsCovariant
<'a
> + ?Sized
> IsCovariant
<'a
> for Rc
<T
> {}
134 // This is safe because T has a covariant lifetime, and Cow's lifetime is also covariant
135 #[cfg(feature = "alloc")]
136 unsafe impl<'a
, T
: IsCovariant
<'a
> + ToOwned
+ ?Sized
> IsCovariant
<'a
> for Cow
<'a
, T
> where
137 <T
as ToOwned
>::Owned
: Sized
141 // This is safe because T has a covariant lifetime, and the reference lifetime is also covariant
142 unsafe impl<'a
, T
: IsCovariant
<'a
> + ?Sized
> IsCovariant
<'a
> for &'a T {}