You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

yoke

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yoke - cargo Package Compare versions

Comparing version
0.6.2
to
0.7.0
+1
-1
.cargo_vcs_info.json
{
"git": {
"sha1": "7a471b7e4584bfc165d9e593295742c880369bf7"
"sha1": "196823aa3a859324cca61b61e7aafa4c98988f1a"
},
"path_in_vcs": "utils/yoke"
}

@@ -15,3 +15,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO

name = "yoke"
version = "0.6.2"
version = "0.7.0"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]

@@ -44,2 +44,5 @@ include = [

[package.metadata.workspaces]
independent = true
[package.metadata.docs.rs]

@@ -58,7 +61,7 @@ all-features = true

[dependencies.yoke-derive]
version = "0.6.0"
version = "0.7.0"
optional = true
[dependencies.zerofrom]
version = "0.1.0"
version = "0.1.1"
optional = true

@@ -76,3 +79,3 @@ default-features = false

"stable_deref_trait/alloc",
"serde/alloc",
"serde?/alloc",
"zerofrom/alloc",

@@ -85,4 +88,4 @@ ]

derive = [
"yoke-derive",
"dep:yoke-derive",
"zerofrom/derive",
]

@@ -10,3 +10,3 @@ // This file is part of ICU4X. For terms of use, please see the file

//!
//! Available with the `"alloc"` feature enabled.
//! Available with the `"alloc"` Cargo feature enabled.

@@ -29,3 +29,3 @@ use alloc::boxed::Box;

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
pub type ErasedArcCart = Arc<dyn ErasedDestructor + Send + Sync>;

@@ -36,3 +36,3 @@ /// A type-erased Cart that has `Rc` semantics

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
pub type ErasedRcCart = Rc<dyn ErasedDestructor>;

@@ -43,3 +43,3 @@ /// A type-erased Cart that has `Box` semantics

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
pub type ErasedBoxCart = Box<dyn ErasedDestructor>;

@@ -51,3 +51,2 @@ // This file is part of ICU4X. For terms of use, please see the file

pub mod erased;
mod is_covariant;
mod macro_impls;

@@ -63,3 +62,2 @@ pub mod trait_hack;

pub use crate::is_covariant::IsCovariant;
pub use crate::yoke::{CloneableCart, Yoke};

@@ -66,0 +64,0 @@ pub use crate::yokeable::Yokeable;

@@ -9,3 +9,3 @@ // This file is part of ICU4X. For terms of use, please see the file

use crate::{IsCovariant, Yokeable};
use crate::Yokeable;
use core::{mem, ptr};

@@ -42,3 +42,2 @@

}
unsafe impl<'a> IsCovariant<'a> for $ty {}
};

@@ -45,0 +44,0 @@ }

@@ -9,3 +9,2 @@ // This file is part of ICU4X. For terms of use, please see the file

use crate::trait_hack::YokeTraitHack;
use crate::IsCovariant;
use crate::Yokeable;

@@ -52,4 +51,3 @@ use core::marker::PhantomData;

///
/// In general, `C` is a concrete type, but it is also possible for it to be a trait object;
/// for more information, see [`IsCovariant`].
/// In general, `C` is a concrete type, but it is also possible for it to be a trait object.
///

@@ -88,3 +86,6 @@ /// # Example

impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C> {
impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>
where
<C as Deref>::Target: 'static,
{
/// Construct a [`Yoke`] by yokeing an object to a cart in a closure.

@@ -122,3 +123,10 @@ ///

where
// safety note: This works by enforcing that the *only* place the return value of F
// can borrow from is the cart, since `F` must be valid for all lifetimes `'de`
//
// The <C as Deref>::Target: 'static on the impl is crucial for safety as well
//
// See safety docs at the bottom of this file for more information
F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
<C as Deref>::Target: 'static,
{

@@ -227,4 +235,6 @@ let deserialized = f(cart.deref());

///
/// let local_data = "foo".to_string();
/// let yoke = Yoke::<&'static str, Box<String>>::attach_to_zero_copy_cart(Box::new(local_data));
/// let local_data = "foo".to_owned();
/// let yoke = Yoke::<&'static str, Box<String>>::attach_to_zero_copy_cart(
/// Box::new(local_data),
/// );
/// assert_eq!(*yoke.get(), "foo");

@@ -243,5 +253,7 @@ ///

///
/// let local_data = "foo".to_string();
/// let local_data = "foo".to_owned();
/// let mut yoke =
/// Yoke::<Cow<'static, str>, Box<String>>::attach_to_zero_copy_cart(Box::new(local_data));
/// Yoke::<Cow<'static, str>, Box<String>>::attach_to_zero_copy_cart(
/// Box::new(local_data),
/// );
/// assert_eq!(yoke.get(), "foo");

@@ -274,2 +286,5 @@ ///

/// returned cart type `C`.
/// - Lifetimes inside C must not be lengthened, even if they are themselves contravariant.
/// I.e., if C contains an `fn(&'a u8)`, it cannot be replaced with `fn(&'static u8),
/// even though that is typically safe.
///

@@ -516,8 +531,5 @@ /// Typically, this means implementing `f` as something which _wraps_ the inner cart type `C`.

// This is safe because Y is 'static and C has a covariant lifetime
unsafe impl<'b, Y: for<'a> Yokeable<'a>, C: IsCovariant<'b>> IsCovariant<'b> for Yoke<Y, C> {}
#[test]
fn test_clone() {
let local_data = "foo".to_string();
let local_data = "foo".to_owned();
let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(

@@ -586,3 +598,5 @@ Rc::new(local_data),

///
/// fn map_project_string_1(bar: Yoke<Bar<'static>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
/// fn map_project_string_1(
/// bar: Yoke<Bar<'static>, Rc<[u8]>>,
/// ) -> Yoke<&'static str, Rc<[u8]>> {
/// bar.map_project(|bar, _| bar.string_1)

@@ -663,3 +677,5 @@ /// }

/// #
/// fn slice(y: Yoke<&'static [u8], Rc<[u8]>>) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
/// fn slice(
/// y: Yoke<&'static [u8], Rc<[u8]>>,
/// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
/// y.try_map_project(move |bytes, _| str::from_utf8(bytes))

@@ -684,3 +700,5 @@ /// }

///
/// fn map_project_string_1(bar: Yoke<Bar<'static>, Rc<[u8]>>) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
/// fn map_project_string_1(
/// bar: Yoke<Bar<'static>, Rc<[u8]>>,
/// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
/// bar.try_map_project(|bar, _| str::from_utf8(bar.bytes_1))

@@ -875,3 +893,4 @@ /// }

///
/// let yoke1 = Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
/// let yoke1 =
/// Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
/// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());

@@ -881,3 +900,4 @@ ///

/// // Wrap the Box in an Rc to make it compatible
/// let erased2: Yoke<_, ErasedRcCart> = yoke2.wrap_cart_in_rc().erase_rc_cart();
/// let erased2: Yoke<_, ErasedRcCart> =
/// yoke2.wrap_cart_in_rc().erase_rc_cart();
///

@@ -887,3 +907,3 @@ /// // Now erased1 and erased2 have the same type!

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart> {

@@ -922,3 +942,4 @@ unsafe {

///
/// let yoke1 = Yoke::<&'static str, _>::attach_to_cart(buffer1, |arc| arc.trim());
/// let yoke1 =
/// Yoke::<&'static str, _>::attach_to_cart(buffer1, |arc| arc.trim());
/// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());

@@ -928,3 +949,4 @@ ///

/// // Wrap the Box in an Rc to make it compatible
/// let erased2: Yoke<_, ErasedArcCart> = yoke2.wrap_cart_in_arc().erase_arc_cart();
/// let erased2: Yoke<_, ErasedArcCart> =
/// yoke2.wrap_cart_in_arc().erase_arc_cart();
///

@@ -934,3 +956,3 @@ /// // Now erased1 and erased2 have the same type!

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_arc_cart(self) -> Yoke<Y, ErasedArcCart> {

@@ -969,7 +991,9 @@ unsafe {

///
/// let yoke1 = Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
/// let yoke1 =
/// Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
/// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
///
/// // Wrap the Rc in an Box to make it compatible
/// let erased1: Yoke<_, ErasedBoxCart> = yoke1.wrap_cart_in_box().erase_box_cart();
/// let erased1: Yoke<_, ErasedBoxCart> =
/// yoke1.wrap_cart_in_box().erase_box_cart();
/// let erased2: Yoke<_, ErasedBoxCart> = yoke2.erase_box_cart();

@@ -980,3 +1004,3 @@ ///

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart> {

@@ -996,3 +1020,3 @@ unsafe {

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
#[inline]

@@ -1009,3 +1033,3 @@ pub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>> {

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
#[inline]

@@ -1022,3 +1046,3 @@ pub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>> {

///
/// Available with the `"alloc"` feature enabled.
/// Available with the `"alloc"` Cargo feature enabled.
#[inline]

@@ -1062,3 +1086,3 @@ pub fn wrap_cart_in_arc(self) -> Yoke<Y, Arc<C>> {

/// Safety docs for project()
/// # Safety docs for project()
///

@@ -1166,1 +1190,149 @@ /// (Docs are on a private const to allow the use of compile_fail doctests)

const _: () = ();
/// # Safety docs for attach_to_cart()'s signature
///
/// The `attach_to_cart()` family of methods get by by using the following bound:
///
/// ```rust,ignore
/// F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
/// C::Target: 'static
/// ```
///
/// to enforce that the yoking closure produces a yokeable that is *only* allowed to borrow from the cart.
/// A way to be sure of this is as follows: imagine if `F` *did* borrow data of lifetime `'a` and stuff it in
/// its output. Then that lifetime `'a` would have to live at least as long as `'de` *for all `'de`*.
/// The only lifetime that satisfies that is `'static` (since at least one of the potential `'de`s is `'static`),
/// and we're fine with that.
///
/// ## Implied bounds and variance
///
/// The `C::Target: 'static` bound is tricky, however. Let's imagine a situation where we *didn't* have that bound.
///
/// One thing to remember is that we are okay with the cart itself borrowing from places,
/// e.g. `&[u8]` is a valid cart, as is `Box<&[u8]>`. `C` is not `'static`.
///
/// (I'm going to use `CT` in prose to refer to `C::Target` here, since almost everything here has to do
/// with C::Target and not C itself.)
///
/// Unfortunately, there's a sneaky additional bound inside `F`. The signature of `F` is *actually*
///
/// ```rust,ignore
/// F: for<'de> where<C::Target: 'de> FnOnce(&'de C::Target) -> <Y as Yokeable<'de>>::Output
/// ```
///
/// using made-up "where clause inside HRTB" syntax to represent a type that can be represented inside the compiler
/// and type system but not in Rust code. The `CT: 'de` bond comes from the `&'de C::Target`: any time you
/// write `&'a T`, an implied bound of `T: 'a` materializes and is stored alongside it, since references cannot refer
/// to data that itself refers to data of shorter lifetimes. If a reference is valid, its referent must be valid for
/// the duration of the reference's lifetime, so every reference *inside* its referent must also be valid, giving us `T: 'a`.
/// This kind of constraint is often called a "well formedness" constraint: `&'a T` is not "well formed" without that
/// bound, and rustc is being helpful by giving it to us for free.
///
/// Unfortunately, this messes with our universal quantification. The `for<'de>` is no longer "For all lifetimes `'de`",
/// it is "for all lifetimes `'de` *where `CT: 'de`*". And if `CT` borrows from somewhere (with lifetime `'ct`), then we get a
/// `'ct: 'de` bound, and `'de` candidates that live longer than `'ct` won't actually be considered.
/// The neat little logic at the beginning stops working.
///
/// `attach_to_cart()` will instead enforce that the produced yokeable *either* borrows from the cart (fine), or from
/// data that has a lifetime that is at least `'ct`. Which means that `attach_to_cart()` will allow us to borrow locals
/// provided they live at least as long as `'ct`.
///
/// Is this a problem?
///
/// This is totally fine if CT's lifetime is covariant: if C is something like `Box<&'ct [u8]>`, even if our
/// yoked object borrows from locals outliving `'ct`, our Yoke can't outlive that
/// lifetime `'ct` anyway (since it's a part of the cart type), so we're fine.
///
/// However it's completely broken for contravariant carts (e.g. `Box<fn(&'ct u8)>`). In that case
/// we still get `'ct: 'de`, and we still end up being able to
/// borrow from locals that outlive `'ct`. However, our Yoke _can_ outlive
/// that lifetime, because Yoke shares its variance over `'ct`
/// with the cart type, and the cart type is contravariant over `'ct`.
/// So the Yoke can be upcast to having a longer lifetime than `'ct`, and *that* Yoke
/// can outlive `'ct`.
///
/// We fix this by forcing `C::Target: 'static` in `attach_to_cart()`, which would make it work
/// for fewer types, but would also allow Yoke to continue to be covariant over cart lifetimes if necessary.
///
/// An alternate fix would be to not allowing yoke to ever be upcast over lifetimes contained in the cart
/// by forcing them to be invariant. This is a bit more restrictive and affects *all* `Yoke` users, not just
/// those using `attach_to_cart()`.
///
/// See https://github.com/unicode-org/icu4x/issues/2926
/// See also https://github.com/rust-lang/rust/issues/106431 for potentially fixing this upstream by
/// changing how the bound works.
///
/// # Tests
///
/// Here's a broken `attach_to_cart()` that attempts to borrow from a local:
///
/// ```rust,compile_fail
/// use yoke::{Yoke, Yokeable};
///
/// let cart = vec![1, 2, 3, 4].into_boxed_slice();
/// let local = vec![4, 5, 6, 7];
/// let yoke: Yoke<&[u8], Box<[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);
/// ```
///
/// Fails as expected.
///
/// And here's a working one with a local borrowed cart that does not do any sneaky borrows whilst attaching.
///
/// ```rust
/// use yoke::{Yoke, Yokeable};
///
/// let cart = vec![1, 2, 3, 4].into_boxed_slice();
/// let local = vec![4, 5, 6, 7];
/// let yoke: Yoke<&[u8], &[u8]> = Yoke::attach_to_cart(&cart, |c| &*c);
/// ```
///
/// Here's an `attach_to_cart()` that attempts to borrow from a longer-lived local due to
/// the cart being covariant. It fails, but would not if the alternate fix of forcing Yoke to be invariant
/// were implemented. It is technically a safe operation:
///
/// ```rust,compile_fail
/// use yoke::{Yoke, Yokeable};
/// // longer lived
/// let local = vec![4, 5, 6, 7];
///
/// let backing = vec![1, 2, 3, 4];
/// let cart = Box::new(&*backing);
///
/// let yoke: Yoke<&[u8], Box<&[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);
/// println!("{:?}", yoke.get());
/// ```
///
/// Finally, here's an `attach_to_cart()` that attempts to borrow from a longer lived local
/// in the case of a contravariant lifetime. It does not compile, but in and of itself is not dangerous:
///
/// ```rust,compile_fail
/// use yoke::Yoke;
///
/// type Contra<'a> = fn(&'a ());
///
/// let local = String::from("Hello World!");
/// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]);
/// println!("{:?}", yoke.get());
/// ```
///
/// It is dangerous if allowed to transform (testcase from #2926)
///
/// ```rust,compile_fail
/// use yoke::Yoke;
///
/// type Contra<'a> = fn(&'a ());
///
///
/// let local = String::from("Hello World!");
/// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]);
/// println!("{:?}", yoke.get());
/// let yoke_longer: Yoke<&'static str, Box<Contra<'static>>> = yoke;
/// let leaked: &'static Yoke<&'static str, Box<Contra<'static>>> = Box::leak(Box::new(yoke_longer));
/// let reference: &'static str = leaked.get();
///
/// println!("pre-drop: {reference}");
/// drop(local);
/// println!("post-drop: {reference}");
///
/// ```
const _: () = ();

@@ -29,2 +29,3 @@ // This file is part of ICU4X. For terms of use, please see the file

C: StableDeref + Deref,
<C as Deref>::Target: 'static,
{

@@ -46,3 +47,5 @@ /// Construct a [`Yoke`]`<Y, C>` from a cart implementing `StableDeref` by zero-copy cloning

///
/// let yoke = Yoke::<Cow<'static, str>, String>::attach_to_zero_copy_cart("demo".to_string());
/// let yoke = Yoke::<Cow<'static, str>, String>::attach_to_zero_copy_cart(
/// "demo".to_owned(),
/// );
///

@@ -49,0 +52,0 @@ /// assert_eq!("demo", yoke.get());

// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
#[cfg(feature = "alloc")]
use alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
rc::Rc,
string::String,
};
/// A type implementing `IsCovariant<'a>` is covariant with respect to lifetime `'a`.
///
/// Lifetime parameters that are safely cast in [`Yokeable`] are also valid for `IsCovariant`.
///
/// `IsCovariant` exists primarily to serve in trait bounds. The primary use case is to safely
/// perform lifetime casting on trait objects (`dyn Trait`). This enables a type-erased [`Yoke`]
/// consisting of only trait objects. See the examples.
///
/// `IsCovariant` is auto-implemented in [`#[derive(Yokeable)]`](macro@crate::Yokeable).
///
/// # Safety
///
/// This trait is safe to implement on types with a _covariant_ lifetime parameter. This will
/// occur when the lifetime parameter is used within references, but not in the arguments of
/// function pointers or in mutable positions (either in `&mut` or via interior mutability).
///
/// If a struct has multiple lifetime parameters, only the one used in `IsCovariant<'a>` needs to
/// be covariant.
///
/// # Examples
///
/// Implementing on a simple struct with a single covariant lifetime:
///
/// ```
/// # use yoke::*;
/// struct MyStruct<'a>(&'a str);
///
/// // This is safe because 'a is covariant
/// unsafe impl<'a> IsCovariant<'a> for MyStruct<'a> {}
/// ```
///
/// By constraining the trait `ExampleTrait<'a>` on `IsCovariant<'a>`, we can safely implement
/// [`Yokeable`] and [`ZeroFrom`] on its trait object:
///
/// ```
/// # use yoke::*;
/// # use zerofrom::*;
/// # use core::mem;
/// trait ExampleTrait<'a>: IsCovariant<'a> {
/// fn get_message(&self) -> &'a str;
/// }
///
/// // This wrapper is required because of the blanket Yokeable impl on &'static T
/// pub struct ExampleTraitDynRef<'a>(pub &'a dyn ExampleTrait<'a>);
///
/// // The following impl is safe because the trait object requires IsCovariant.
/// unsafe impl<'a> Yokeable<'a> for ExampleTraitDynRef<'static> {
/// type Output = ExampleTraitDynRef<'a>;
/// fn transform(&'a self) -> &'a Self::Output {
/// unsafe { mem::transmute(self) }
/// }
///
/// fn transform_owned(self) -> Self::Output {
/// unsafe { mem::transmute(self) }
/// }
///
/// unsafe fn make(from: Self::Output) -> Self {
/// unsafe { mem::transmute(from) }
/// }
///
/// fn transform_mut<F>(&'a mut self, f: F)
/// where
/// F: 'static + FnOnce(&'a mut Self::Output),
/// {
/// unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
/// }
/// }
///
/// impl<'zf, 'a> ZeroFrom<'zf, dyn ExampleTrait<'a> + 'a> for ExampleTraitDynRef<'zf> {
/// fn zero_from(this: &'zf (dyn ExampleTrait<'a> + 'a)) -> ExampleTraitDynRef<'zf> {
/// // This is safe because the trait object requires IsCovariant.
/// ExampleTraitDynRef(unsafe { core::mem::transmute(this) })
/// }
/// }
///
/// // Implement ExampleTrait on the struct from the previous example
/// # struct MyStruct<'a>(&'a str);
/// # unsafe impl<'a> IsCovariant<'a> for MyStruct<'a> {}
/// impl<'a> ExampleTrait<'a> for MyStruct<'a> {
/// fn get_message(&self) -> &'a str {
/// self.0
/// }
/// }
///
/// // Example usage: a Yoke of a trait object
/// let s = "Hello World".to_string();
/// let yoke: Yoke<ExampleTraitDynRef<'static>, Box<dyn ExampleTrait>> =
/// Yoke::attach_to_zero_copy_cart(Box::new(MyStruct(&s)));
///
/// assert_eq!(yoke.get().0.get_message(), "Hello World");
/// ```
///
/// [`Yoke`]: crate::Yoke
/// [`Yokeable`]: crate::Yokeable
/// [`ZeroFrom`]: crate::ZeroFrom
pub unsafe trait IsCovariant<'a>: 'a {}
// IsCovariant is implemented on the standard library Copy types in macro_impls.rs
// The following impls are safe because there is only one lifetime, 'a, and 'a is covariant
unsafe impl<'a> IsCovariant<'a> for () {}
unsafe impl<'a> IsCovariant<'a> for str {}
#[cfg(feature = "alloc")]
unsafe impl<'a> IsCovariant<'a> for String {}
unsafe impl<'a, T: IsCovariant<'a>> IsCovariant<'a> for Option<T> {}
unsafe impl<'a, T1: IsCovariant<'a>, T2: IsCovariant<'a>> IsCovariant<'a> for (T1, T2) {}
unsafe impl<'a, T: IsCovariant<'a>> IsCovariant<'a> for [T] {}
unsafe impl<'a, T: IsCovariant<'a>, const N: usize> IsCovariant<'a> for [T; N] {}
#[cfg(feature = "alloc")]
unsafe impl<'a, T: IsCovariant<'a> + ?Sized> IsCovariant<'a> for Box<T> {}
#[cfg(feature = "alloc")]
unsafe impl<'a, T: IsCovariant<'a> + ?Sized> IsCovariant<'a> for Rc<T> {}
// This is safe because T has a covariant lifetime, and Cow's lifetime is also covariant
#[cfg(feature = "alloc")]
unsafe impl<'a, T: IsCovariant<'a> + ToOwned + ?Sized> IsCovariant<'a> for Cow<'a, T> where
<T as ToOwned>::Owned: Sized
{
}
// This is safe because T has a covariant lifetime, and the reference lifetime is also covariant
unsafe impl<'a, T: IsCovariant<'a> + ?Sized> IsCovariant<'a> for &'a T {}

Sorry, the diff of this file is not supported yet