diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:41 +0000 |
commit | 4f9fe856a25ab29345b90e7725509e9ee38a37be (patch) | |
tree | e4ffd8a9374cae7b21f7cbfb352927e0e074aff6 /vendor/yoke-derive/src | |
parent | Adding upstream version 1.68.2+dfsg1. (diff) | |
download | rustc-4f9fe856a25ab29345b90e7725509e9ee38a37be.tar.xz rustc-4f9fe856a25ab29345b90e7725509e9ee38a37be.zip |
Adding upstream version 1.69.0+dfsg1.upstream/1.69.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/yoke-derive/src')
-rw-r--r-- | vendor/yoke-derive/src/lib.rs | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/vendor/yoke-derive/src/lib.rs b/vendor/yoke-derive/src/lib.rs index 615669d84..4c53bef68 100644 --- a/vendor/yoke-derive/src/lib.rs +++ b/vendor/yoke-derive/src/lib.rs @@ -81,8 +81,6 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { f(self) } } - // This is safe because there are no lifetime parameters. - unsafe impl<'a, #(#tybounds),*> yoke::IsCovariant<'a> for #name<#(#typarams),*> where #(#static_bounds),* {} } } else { if lts != 1 { @@ -110,11 +108,11 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { .collect(); let mut yoke_bounds: Vec<WherePredicate> = vec![]; structure.bind_with(|_| synstructure::BindStyle::Move); - let body = structure.each_variant(|vi| { + let owned_body = structure.each_variant(|vi| { vi.construct(|f, i| { let binding = format!("__binding_{}", i); let field = Ident::new(&binding, Span::call_site()); - let fty = replace_lifetime(&f.ty, static_lt()); + let fty_static = replace_lifetime(&f.ty, static_lt()); let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env); if has_ty { @@ -123,11 +121,14 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { // to `FieldTy: Yokeable` that need to be satisfied. We get them to be satisfied by requiring // `FieldTy<'static>: Yokeable<FieldTy<'a>>` if has_lt { - let a_ty = replace_lifetime(&f.ty, custom_lt("'a")); - yoke_bounds - .push(parse_quote!(#fty: yoke::Yokeable<'a, Output = #a_ty>)); + let fty_a = replace_lifetime(&f.ty, custom_lt("'a")); + yoke_bounds.push( + parse_quote!(#fty_static: yoke::Yokeable<'a, Output = #fty_a>), + ); } else { - yoke_bounds.push(parse_quote!(#fty: yoke::Yokeable<'a, Output = #fty>)); + yoke_bounds.push( + parse_quote!(#fty_static: yoke::Yokeable<'a, Output = #fty_static>), + ); } } if has_ty || has_lt { @@ -135,7 +136,7 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { // that the lifetimes are covariant, since this requirement // must already be true for the type that implements transform_owned(). quote! { - <#fty as yoke::Yokeable<'a>>::transform_owned(#field) + <#fty_static as yoke::Yokeable<'a>>::transform_owned(#field) } } else { // No nested lifetimes, so nothing to be done @@ -143,6 +144,30 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { } }) }); + let borrowed_body = structure.each(|binding| { + let f = binding.ast(); + let field = &binding.binding; + + let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env); + + if has_ty || has_lt { + let fty_static = replace_lifetime(&f.ty, static_lt()); + let fty_a = replace_lifetime(&f.ty, custom_lt("'a")); + // We also must assert that each individual field can `transform()` correctly + // + // Even though transform_owned() does such an assertion already, CoerceUnsized + // can cause type transformations that allow it to succeed where this would fail. + // We need to check both. + // + // https://github.com/unicode-org/icu4x/issues/2928 + quote! { + let _: &#fty_a = &<#fty_static as yoke::Yokeable<'a>>::transform(#field); + } + } else { + // No nested lifetimes, so nothing to be done + quote! {} + } + }); return quote! { unsafe impl<'a, #(#tybounds),*> yoke::Yokeable<'a> for #name<'static, #(#typarams),*> where #(#static_bounds,)* @@ -150,6 +175,12 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { type Output = #name<'a, #(#typarams),*>; #[inline] fn transform(&'a self) -> &'a Self::Output { + // These are just type asserts, we don't need them for anything + if false { + match self { + #borrowed_body + } + } unsafe { // safety: we have asserted covariance in // transform_owned @@ -158,7 +189,7 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { } #[inline] fn transform_owned(self) -> Self::Output { - match self { #body } + match self { #owned_body } } #[inline] unsafe fn make(this: Self::Output) -> Self { @@ -206,6 +237,7 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { // are the same debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); let ptr: *const Self = (&this as *const Self::Output).cast(); + #[allow(clippy::forget_copy)] // This is a noop if the struct is copy, which Clippy doesn't like mem::forget(this); ptr::read(ptr) } @@ -216,9 +248,6 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 { unsafe { f(core::mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) } } } - // This is safe because it is in the same block as the above impl, which only compiles - // if 'a is a covariant lifetime. - unsafe impl<'a, #(#tybounds),*> yoke::IsCovariant<'a> for #name<'a, #(#typarams),*> where #(#static_bounds),* {} } } } |