diff --git a/experimental/segmenter/src/provider.rs b/experimental/segmenter/src/provider.rs index 22e38e487f2..cd5f1939238 100644 --- a/experimental/segmenter/src/provider.rs +++ b/experimental/segmenter/src/provider.rs @@ -61,8 +61,8 @@ impl Deref for LineBreakPropertyTable<'_> { } } -impl<'a> ZeroCopyFrom> for LineBreakPropertyTable<'static> { - fn zero_copy_from<'b>(cart: &'b LineBreakPropertyTable<'a>) -> >::Output { +impl<'zcf> ZeroCopyFrom<'zcf, LineBreakPropertyTable<'_>> for LineBreakPropertyTable<'zcf> { + fn zero_copy_from(cart: &'zcf LineBreakPropertyTable<'_>) -> Self { LineBreakPropertyTable::Borrowed(&*cart) } } diff --git a/provider/core/src/erased.rs b/provider/core/src/erased.rs index f79f66494c8..d01bc7ee013 100644 --- a/provider/core/src/erased.rs +++ b/provider/core/src/erased.rs @@ -53,9 +53,8 @@ pub trait ErasedDataStruct: 'static { fn as_any(&self) -> &dyn Any; } -impl ZeroCopyFrom for &'static dyn ErasedDataStruct { - #[allow(clippy::needless_lifetimes)] - fn zero_copy_from<'b>(this: &'b (dyn ErasedDataStruct)) -> &'b dyn ErasedDataStruct { +impl<'zcf> ZeroCopyFrom<'zcf, dyn ErasedDataStruct> for &'zcf dyn ErasedDataStruct { + fn zero_copy_from(this: &'zcf (dyn ErasedDataStruct)) -> &'zcf dyn ErasedDataStruct { this } } diff --git a/utils/yoke/derive/examples/derive.rs b/utils/yoke/derive/examples/derive.rs index f4a7fff0094..b752a0a6493 100644 --- a/utils/yoke/derive/examples/derive.rs +++ b/utils/yoke/derive/examples/derive.rs @@ -51,12 +51,12 @@ pub struct HasTuples<'data> { } pub fn assert_zcf_tuples<'b, 'data>(x: &'b HasTuples<'data>) -> HasTuples<'b> { - HasTuples::<'static>::zero_copy_from(x) + HasTuples::zero_copy_from(x) } pub fn assert_zcf_generics<'a, 'b>( x: &'b ZeroVecExampleWithGenerics<'a, u8>, ) -> ZeroVecExampleWithGenerics<'b, u8> { - ZeroVecExampleWithGenerics::<'static, u8>::zero_copy_from(x) + ZeroVecExampleWithGenerics::<'b, u8>::zero_copy_from(x) } // Since ZeroMap has generic parameters, the Rust compiler cannot @@ -78,7 +78,7 @@ pub struct ZeroMapGenericExample<'a, T: for<'b> ZeroMapKV<'b> + ?Sized> { pub fn assert_zcf_map<'a, 'b>( x: &'b ZeroMapGenericExample<'a, str>, ) -> ZeroMapGenericExample<'b, str> { - ZeroMapGenericExample::<'static, str>::zero_copy_from(x) + ZeroMapGenericExample::zero_copy_from(x) } #[derive(Yokeable, Clone, ZeroCopyFrom)] diff --git a/utils/yoke/derive/src/lib.rs b/utils/yoke/derive/src/lib.rs index 59fcb1123ed..da8041b4255 100644 --- a/utils/yoke/derive/src/lib.rs +++ b/utils/yoke/derive/src/lib.rs @@ -253,8 +253,8 @@ fn zcf_derive_impl(input: &DeriveInput) -> TokenStream2 { .map(|ty| parse_quote!(#ty: #clone_trait + 'static)) .collect(); quote! { - impl<#(#tybounds),*> ZeroCopyFrom<#name<#(#typarams),*>> for #name<#(#typarams),*> where #(#bounds),* { - fn zero_copy_from(this: &Self) -> Self { + impl<'zcf, #(#tybounds),*> ZeroCopyFrom<'zcf, #name<#(#typarams),*>> for #name<#(#typarams),*> where #(#bounds),* { + fn zero_copy_from(this: &'zcf Self) -> Self { #clone } } @@ -269,8 +269,8 @@ fn zcf_derive_impl(input: &DeriveInput) -> TokenStream2 { } if has_clone { return quote! { - impl<'data> ZeroCopyFrom<#name<'data>> for #name<'static> { - fn zero_copy_from<'b>(this: &'b #name<'data>) -> #name<'b> { + impl<'zcf> ZeroCopyFrom<'zcf, #name<'_>> for #name<'zcf> { + fn zero_copy_from(this: &'zcf #name<'_>) -> Self { this.clone() } } @@ -279,10 +279,6 @@ fn zcf_derive_impl(input: &DeriveInput) -> TokenStream2 { let structure = Structure::new(input); let generics_env = typarams.iter().cloned().collect(); - let static_bounds: Vec = typarams - .iter() - .map(|ty| parse_quote!(#ty: 'static)) - .collect(); let mut zcf_bounds: Vec = vec![]; let body = structure.each_variant(|vi| { @@ -292,46 +288,42 @@ fn zcf_derive_impl(input: &DeriveInput) -> TokenStream2 { let binding = format!("__binding_{}", i); let field = Ident::new(&binding, Span::call_site()); - if binding_cloning { quote! { #field.clone() } } else { - let fty = replace_lifetime(&f.ty, static_lt()); - let lifetime_ty = replace_lifetime(&f.ty, custom_lt("'data")); + let fty = replace_lifetime(&f.ty, custom_lt("'zcf")); + let lifetime_ty = replace_lifetime(&f.ty, custom_lt("'zcf_inner")); let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env); if has_ty { // For types without type parameters, the compiler can figure out that the field implements // ZeroCopyFrom on its own. However, if there are type parameters, there may be complex preconditions // to `FieldTy: ZeroCopyFrom` that need to be satisfied. We get them to be satisfied by requiring - // `FieldTy<'static>: ZeroCopyFrom>` as well as - // `for<'data_hrtb> FieldTy<'static>: Yokeable<'data_hrtb, Output = FieldTy<'data_hrtb>>` + // `FieldTy<'zcf>: ZeroCopyFrom<'zcf, FieldTy<'zcf_inner>>` if has_lt { - let hrtb_ty = replace_lifetime(&f.ty, custom_lt("'data_hrtb")); - zcf_bounds.push(parse_quote!(#fty: yoke::ZeroCopyFrom<#lifetime_ty>)); - zcf_bounds.push(parse_quote!(for<'data_hrtb> #fty: yoke::Yokeable<'data_hrtb, Output = #hrtb_ty>)); + zcf_bounds + .push(parse_quote!(#fty: yoke::ZeroCopyFrom<'zcf, #lifetime_ty>)); } else { - zcf_bounds.push(parse_quote!(#fty: yoke::ZeroCopyFrom<#fty>)); - zcf_bounds.push(parse_quote!(for<'data_hrtb> #fty: yoke::Yokeable<'data_hrtb, Output = #fty>)); + zcf_bounds.push(parse_quote!(#fty: yoke::ZeroCopyFrom<'zcf, #fty>)); } } // By doing this we essentially require ZCF to be implemented // on all fields quote! { - <#fty as yoke::ZeroCopyFrom<#lifetime_ty>>::zero_copy_from(#field) + <#fty as yoke::ZeroCopyFrom<'zcf, #lifetime_ty>>::zero_copy_from(#field) } } }) }); quote! { - impl<'data, #(#tybounds),*> yoke::ZeroCopyFrom<#name<'data, #(#typarams),*>> for #name<'static, #(#typarams),*> - where #(#static_bounds,)* + impl<'zcf, 'zcf_inner, #(#tybounds),*> yoke::ZeroCopyFrom<'zcf, #name<'zcf_inner, #(#typarams),*>> for #name<'zcf, #(#typarams),*> + where #(#zcf_bounds,)* { - fn zero_copy_from<'b>(this: &'b #name<'data, #(#typarams),*>) -> #name<'b, #(#typarams),*> { + fn zero_copy_from(this: &'zcf #name<'zcf_inner, #(#typarams),*>) -> Self { match *this { #body } } } diff --git a/utils/yoke/src/is_covariant.rs b/utils/yoke/src/is_covariant.rs index 53c7a0eeb58..880fc52d57c 100644 --- a/utils/yoke/src/is_covariant.rs +++ b/utils/yoke/src/is_covariant.rs @@ -77,8 +77,8 @@ use alloc::{ /// } /// } /// -/// impl<'a> ZeroCopyFrom + 'a> for ExampleTraitDynRef<'static> { -/// fn zero_copy_from<'b>(this: &'b (dyn ExampleTrait<'a> + 'a)) -> ExampleTraitDynRef<'b> { +/// impl<'zcf, 'a> ZeroCopyFrom<'zcf, dyn ExampleTrait<'a> + 'a> for ExampleTraitDynRef<'zcf> { +/// fn zero_copy_from(this: &'zcf (dyn ExampleTrait<'a> + 'a)) -> ExampleTraitDynRef<'zcf> { /// // This is safe because the trait object requires IsCovariant. /// ExampleTraitDynRef(unsafe { core::mem::transmute(this) }) /// } diff --git a/utils/yoke/src/macro_impls.rs b/utils/yoke/src/macro_impls.rs index d64bec260fc..a57ae4e1506 100644 --- a/utils/yoke/src/macro_impls.rs +++ b/utils/yoke/src/macro_impls.rs @@ -38,9 +38,9 @@ macro_rules! impl_copy_type { type Output = Self; copy_yoke_impl!(); } - impl ZeroCopyFrom<$ty> for $ty { + impl<'a> ZeroCopyFrom<'a, $ty> for $ty { #[inline] - fn zero_copy_from(this: &Self) -> Self { + fn zero_copy_from(this: &'a Self) -> Self { // Essentially only works when the struct is fully Copy *this } @@ -117,8 +117,8 @@ unsafe impl<'a, T: Yokeable<'a>, const N: usize> Yokeable<'a> for [T; N] { // https://github.com/rust-lang/rust/issues/76118 macro_rules! array_zcf_impl { ($n:expr; $($i:expr),+) => { - impl> ZeroCopyFrom<[C; $n]> for [T; $n] { - fn zero_copy_from<'b>(this: &'b [C; $n]) -> [>::Output; $n] { + impl<'a, C, T: ZeroCopyFrom<'a, C>> ZeroCopyFrom<'a, [C; $n]> for [T; $n] { + fn zero_copy_from(this: &'a [C; $n]) -> Self { [ $( >::zero_copy_from(&this[$i]) diff --git a/utils/yoke/src/zero_copy_from.rs b/utils/yoke/src/zero_copy_from.rs index d601f32a4f9..445de738496 100644 --- a/utils/yoke/src/zero_copy_from.rs +++ b/utils/yoke/src/zero_copy_from.rs @@ -2,6 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). +use crate::trait_hack::YokeTraitHack; use crate::Yoke; use crate::Yokeable; #[cfg(feature = "alloc")] @@ -35,34 +36,9 @@ use stable_deref_trait::StableDeref; /// message: Cow<'data, str>, /// } /// -/// unsafe impl<'a> Yokeable<'a> for MyStruct<'static> { -/// // (not shown; see `Yokeable` for examples) -/// # type Output = MyStruct<'a>; -/// # fn transform(&'a self) -> &'a Self::Output { -/// # self -/// # } -/// # fn transform_owned(self) -> MyStruct<'a> { -/// # // covariant lifetime cast, can be done safely -/// # self -/// # } -/// # unsafe fn make(from: Self::Output) -> Self { -/// # std::mem::transmute(from) -/// # } -/// # fn transform_mut(&'a mut self, f: F) -/// # where -/// # F: 'static + for<'b> FnOnce(&'b mut Self::Output), -/// # { -/// # unsafe { -/// # f(std::mem::transmute::<&'a mut Self, &'a mut Self::Output>( -/// # self, -/// # )) -/// # } -/// # } -/// } -/// /// // Reference from a borrowed version of self -/// impl<'data> ZeroCopyFrom> for MyStruct<'static> { -/// fn zero_copy_from<'b>(cart: &'b MyStruct<'data>) -> MyStruct<'b> { +/// impl<'zcf> ZeroCopyFrom<'zcf, MyStruct<'_>> for MyStruct<'zcf> { +/// fn zero_copy_from(cart: &'zcf MyStruct<'_>) -> Self { /// MyStruct { /// message: Cow::Borrowed(&cart.message) /// } @@ -70,22 +46,33 @@ use stable_deref_trait::StableDeref; /// } /// /// // Reference from a string slice directly -/// impl ZeroCopyFrom for MyStruct<'static> { -/// fn zero_copy_from<'b>(cart: &'b str) -> MyStruct<'b> { +/// impl<'zcf> ZeroCopyFrom<'zcf, str> for MyStruct<'zcf> { +/// fn zero_copy_from(cart: &'zcf str) -> Self { /// MyStruct { /// message: Cow::Borrowed(cart) /// } /// } /// } /// ``` -pub trait ZeroCopyFrom: for<'a> Yokeable<'a> { - /// Clone the cart `C` into a [`Yokeable`] struct, which may retain references into `C`. - fn zero_copy_from<'b>(cart: &'b C) -> >::Output; +pub trait ZeroCopyFrom<'zcf, C: ?Sized>: 'zcf { + /// Clone the cart `C` into a struct that may retain references into `C`. + fn zero_copy_from(cart: &'zcf C) -> Self; +} + +impl<'zcf, C: ?Sized, T> ZeroCopyFrom<'zcf, C> for YokeTraitHack +where + T: ZeroCopyFrom<'zcf, C>, +{ + #[inline] + fn zero_copy_from(cart: &'zcf C) -> Self { + YokeTraitHack(T::zero_copy_from(cart)) + } } -impl<'b, 's, Y, C> Yoke +impl Yoke where - Y: for<'a> Yokeable<'a> + ZeroCopyFrom<::Target>, + Y: for<'a> Yokeable<'a>, + for<'a> YokeTraitHack<>::Output>: ZeroCopyFrom<'a, ::Target>, C: StableDeref + Deref, { /// Construct a [`Yoke`]`` from a cart implementing `StableDeref` by zero-copy cloning @@ -110,9 +97,10 @@ where /// /// assert_eq!("demo", yoke.get()); /// ``` - #[inline] pub fn attach_to_zero_copy_cart(cart: C) -> Self { - Yoke::::attach_to_cart_badly(cart, Y::zero_copy_from) + Yoke::::attach_to_cart(cart, |c| { + YokeTraitHack::<::Output>::zero_copy_from(c).0 + }) } } @@ -122,47 +110,47 @@ where // specialization. #[cfg(feature = "alloc")] -impl ZeroCopyFrom for Cow<'static, str> { +impl<'zcf> ZeroCopyFrom<'zcf, str> for Cow<'zcf, str> { #[inline] - fn zero_copy_from<'b>(cart: &'b str) -> Cow<'b, str> { + fn zero_copy_from(cart: &'zcf str) -> Self { Cow::Borrowed(cart) } } #[cfg(feature = "alloc")] -impl ZeroCopyFrom for Cow<'static, str> { +impl<'zcf> ZeroCopyFrom<'zcf, String> for Cow<'zcf, str> { #[inline] - fn zero_copy_from<'b>(cart: &'b String) -> Cow<'b, str> { + fn zero_copy_from(cart: &'zcf String) -> Self { Cow::Borrowed(cart) } } -impl ZeroCopyFrom for &'static str { +impl<'zcf> ZeroCopyFrom<'zcf, str> for &'zcf str { #[inline] - fn zero_copy_from<'b>(cart: &'b str) -> &'b str { + fn zero_copy_from(cart: &'zcf str) -> Self { cart } } #[cfg(feature = "alloc")] -impl ZeroCopyFrom for &'static str { +impl<'zcf> ZeroCopyFrom<'zcf, String> for &'zcf str { #[inline] - fn zero_copy_from<'b>(cart: &'b String) -> &'b str { + fn zero_copy_from(cart: &'zcf String) -> Self { cart } } -impl> ZeroCopyFrom> for Option { - fn zero_copy_from<'b>(cart: &'b Option) -> Option<>::Output> { +impl<'zcf, C, T: ZeroCopyFrom<'zcf, C>> ZeroCopyFrom<'zcf, Option> for Option { + fn zero_copy_from(cart: &'zcf Option) -> Self { cart.as_ref() .map(|c| >::zero_copy_from(c)) } } -impl, C2, T2: ZeroCopyFrom> ZeroCopyFrom<(C1, C2)> for (T1, T2) { - fn zero_copy_from<'b>( - cart: &'b (C1, C2), - ) -> (>::Output, >::Output) { +impl<'zcf, C1, T1: ZeroCopyFrom<'zcf, C1>, C2, T2: ZeroCopyFrom<'zcf, C2>> + ZeroCopyFrom<'zcf, (C1, C2)> for (T1, T2) +{ + fn zero_copy_from(cart: &'zcf (C1, C2)) -> Self { ( >::zero_copy_from(&cart.0), >::zero_copy_from(&cart.1), @@ -177,23 +165,23 @@ impl, C2, T2: ZeroCopyFrom> ZeroCopyFrom<(C1, C2)> // or inference are involved, and the proc macro does not necessarily have // enough type information to figure this out on its own. #[cfg(feature = "alloc")] -impl ZeroCopyFrom> for Cow<'static, B> { +impl<'zcf, B: ToOwned + ?Sized> ZeroCopyFrom<'zcf, Cow<'_, B>> for Cow<'zcf, B> { #[inline] - fn zero_copy_from<'b>(cart: &'b Cow<'_, B>) -> Cow<'b, B> { + fn zero_copy_from(cart: &'zcf Cow<'_, B>) -> Self { Cow::Borrowed(cart) } } -impl ZeroCopyFrom<&'_ str> for &'static str { +impl<'zcf> ZeroCopyFrom<'zcf, &'_ str> for &'zcf str { #[inline] - fn zero_copy_from<'b>(cart: &'b &'_ str) -> &'b str { + fn zero_copy_from(cart: &'zcf &'_ str) -> &'zcf str { cart } } -impl ZeroCopyFrom<[T]> for &'static [T] { +impl<'zcf, T> ZeroCopyFrom<'zcf, [T]> for &'zcf [T] { #[inline] - fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] { + fn zero_copy_from(cart: &'zcf [T]) -> &'zcf [T] { cart } } diff --git a/utils/zerovec/src/yoke_impls.rs b/utils/zerovec/src/yoke_impls.rs index 555858e475a..77ad437ea4a 100644 --- a/utils/zerovec/src/yoke_impls.rs +++ b/utils/zerovec/src/yoke_impls.rs @@ -263,70 +263,57 @@ where } } -impl<'a, T: 'static + AsULE + ?Sized> ZeroCopyFrom> for ZeroVec<'static, T> { +impl<'zcf, T> ZeroCopyFrom<'zcf, ZeroVec<'_, T>> for ZeroVec<'zcf, T> +where + T: 'static + AsULE + ?Sized, +{ #[inline] - fn zero_copy_from<'b>(cart: &'b ZeroVec<'a, T>) -> ZeroVec<'b, T> { + fn zero_copy_from(cart: &'zcf ZeroVec<'_, T>) -> Self { ZeroVec::Borrowed(cart.as_ule_slice()) } } -impl<'a, T: 'static + VarULE + ?Sized> ZeroCopyFrom> for VarZeroVec<'static, T> { +impl<'zcf, T> ZeroCopyFrom<'zcf, VarZeroVec<'_, T>> for VarZeroVec<'zcf, T> +where + T: 'static + VarULE + ?Sized, +{ #[inline] - fn zero_copy_from<'b>(cart: &'b VarZeroVec<'a, T>) -> VarZeroVec<'b, T> { + fn zero_copy_from(cart: &'zcf VarZeroVec<'_, T>) -> Self { cart.as_slice().into() } } -impl<'a, K, V> ZeroCopyFrom> for ZeroMap<'static, K, V> +impl<'zcf, 's, K, V> ZeroCopyFrom<'zcf, ZeroMap<'s, K, V>> for ZeroMap<'zcf, K, V> where K: 'static + for<'b> ZeroMapKV<'b> + ?Sized, V: 'static + for<'b> ZeroMapKV<'b> + ?Sized, - >::Container: for<'b> ZeroCopyFrom<>::Container>, - >::Container: for<'b> ZeroCopyFrom<>::Container>, - >::Container: - for<'b> Yokeable<'b, Output = >::Container>, - >::Container: - for<'b> Yokeable<'b, Output = >::Container>, + >::Container: ZeroCopyFrom<'zcf, >::Container>, + >::Container: ZeroCopyFrom<'zcf, >::Container>, { - fn zero_copy_from<'b>(cart: &'b ZeroMap<'a, K, V>) -> ZeroMap<'b, K, V> { + fn zero_copy_from(cart: &'zcf ZeroMap<'s, K, V>) -> Self { ZeroMap { - keys: <>::Container as ZeroCopyFrom<_>>::zero_copy_from( - &cart.keys, - ), - values: <>::Container as ZeroCopyFrom<_>>::zero_copy_from( - &cart.values, - ), + keys: K::Container::zero_copy_from(&cart.keys), + values: V::Container::zero_copy_from(&cart.values), } } } -impl<'a, K0, K1, V> ZeroCopyFrom> for ZeroMap2d<'static, K0, K1, V> +impl<'zcf, 's, K0, K1, V> ZeroCopyFrom<'zcf, ZeroMap2d<'s, K0, K1, V>> + for ZeroMap2d<'zcf, K0, K1, V> where K0: 'static + for<'b> ZeroMapKV<'b> + ?Sized, K1: 'static + for<'b> ZeroMapKV<'b> + ?Sized, V: 'static + for<'b> ZeroMapKV<'b> + ?Sized, - >::Container: for<'b> ZeroCopyFrom<>::Container>, - >::Container: for<'b> ZeroCopyFrom<>::Container>, - >::Container: for<'b> ZeroCopyFrom<>::Container>, - >::Container: - for<'b> Yokeable<'b, Output = >::Container>, - >::Container: - for<'b> Yokeable<'b, Output = >::Container>, - >::Container: - for<'b> Yokeable<'b, Output = >::Container>, + >::Container: ZeroCopyFrom<'zcf, >::Container>, + >::Container: ZeroCopyFrom<'zcf, >::Container>, + >::Container: ZeroCopyFrom<'zcf, >::Container>, { - fn zero_copy_from<'b>(cart: &'b ZeroMap2d<'a, K0, K1, V>) -> ZeroMap2d<'b, K0, K1, V> { + fn zero_copy_from(cart: &'zcf ZeroMap2d<'s, K0, K1, V>) -> Self { ZeroMap2d { - keys0: <>::Container as ZeroCopyFrom<_>>::zero_copy_from( - &cart.keys0, - ), + keys0: K0::Container::zero_copy_from(&cart.keys0), joiner: ZeroVec::zero_copy_from(&cart.joiner), - keys1: <>::Container as ZeroCopyFrom<_>>::zero_copy_from( - &cart.keys1, - ), - values: <>::Container as ZeroCopyFrom<_>>::zero_copy_from( - &cart.values, - ), + keys1: K1::Container::zero_copy_from(&cart.keys1), + values: V::Container::zero_copy_from(&cart.values), } } }