1*5f85604cSMiguel Ojeda // SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT 2*5f85604cSMiguel Ojeda 3b437b383SMiguel Ojeda use proc_macro2::TokenStream; 4b437b383SMiguel Ojeda use quote::quote; 5b437b383SMiguel Ojeda use syn::{parse_quote, Data, Error, Type}; 6b437b383SMiguel Ojeda 7b437b383SMiguel Ojeda use crate::{ 8b437b383SMiguel Ojeda repr::StructUnionRepr, 9b437b383SMiguel Ojeda util::{Ctx, DataExt, FieldBounds, ImplBlockBuilder, SelfBounds, Trait}, 10b437b383SMiguel Ojeda }; 11b437b383SMiguel Ojeda 12b437b383SMiguel Ojeda fn derive_known_layout_for_repr_c_struct<'a>( 13b437b383SMiguel Ojeda ctx: &'a Ctx, 14b437b383SMiguel Ojeda repr: &StructUnionRepr, 15b437b383SMiguel Ojeda fields: &[(&'a syn::Visibility, TokenStream, &'a Type)], 16b437b383SMiguel Ojeda ) -> Option<(SelfBounds<'a>, TokenStream, Option<TokenStream>)> { 17b437b383SMiguel Ojeda let (trailing_field, leading_fields) = fields.split_last()?; 18b437b383SMiguel Ojeda 19b437b383SMiguel Ojeda let (_vis, trailing_field_name, trailing_field_ty) = trailing_field; 20b437b383SMiguel Ojeda let leading_fields_tys = leading_fields.iter().map(|(_vis, _name, ty)| ty); 21b437b383SMiguel Ojeda 22b437b383SMiguel Ojeda let core = ctx.core_path(); 23b437b383SMiguel Ojeda let repr_align = repr 24b437b383SMiguel Ojeda .get_align() 25b437b383SMiguel Ojeda .map(|align| { 26b437b383SMiguel Ojeda let align = align.t.get(); 27b437b383SMiguel Ojeda quote!(#core::num::NonZeroUsize::new(#align as usize)) 28b437b383SMiguel Ojeda }) 29b437b383SMiguel Ojeda .unwrap_or_else(|| quote!(#core::option::Option::None)); 30b437b383SMiguel Ojeda let repr_packed = repr 31b437b383SMiguel Ojeda .get_packed() 32b437b383SMiguel Ojeda .map(|packed| { 33b437b383SMiguel Ojeda let packed = packed.get(); 34b437b383SMiguel Ojeda quote!(#core::num::NonZeroUsize::new(#packed as usize)) 35b437b383SMiguel Ojeda }) 36b437b383SMiguel Ojeda .unwrap_or_else(|| quote!(#core::option::Option::None)); 37b437b383SMiguel Ojeda 38b437b383SMiguel Ojeda let zerocopy_crate = &ctx.zerocopy_crate; 39b437b383SMiguel Ojeda let make_methods = |trailing_field_ty| { 40b437b383SMiguel Ojeda quote! { 41b437b383SMiguel Ojeda // SAFETY: 42b437b383SMiguel Ojeda // - The returned pointer has the same address and provenance as 43b437b383SMiguel Ojeda // `bytes`: 44b437b383SMiguel Ojeda // - The recursive call to `raw_from_ptr_len` preserves both 45b437b383SMiguel Ojeda // address and provenance. 46b437b383SMiguel Ojeda // - The `as` cast preserves both address and provenance. 47b437b383SMiguel Ojeda // - `NonNull::new_unchecked` preserves both address and 48b437b383SMiguel Ojeda // provenance. 49b437b383SMiguel Ojeda // - If `Self` is a slice DST, the returned pointer encodes 50b437b383SMiguel Ojeda // `elems` elements in the trailing slice: 51b437b383SMiguel Ojeda // - This is true of the recursive call to `raw_from_ptr_len`. 52b437b383SMiguel Ojeda // - `trailing.as_ptr() as *mut Self` preserves trailing slice 53b437b383SMiguel Ojeda // element count [1]. 54b437b383SMiguel Ojeda // - `NonNull::new_unchecked` preserves trailing slice element 55b437b383SMiguel Ojeda // count. 56b437b383SMiguel Ojeda // 57b437b383SMiguel Ojeda // [1] Per https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast: 58b437b383SMiguel Ojeda // 59b437b383SMiguel Ojeda // `*const T`` / `*mut T` can be cast to `*const U` / `*mut U` 60b437b383SMiguel Ojeda // with the following behavior: 61b437b383SMiguel Ojeda // ... 62b437b383SMiguel Ojeda // - If `T` and `U` are both unsized, the pointer is also 63b437b383SMiguel Ojeda // returned unchanged. In particular, the metadata is 64b437b383SMiguel Ojeda // preserved exactly. 65b437b383SMiguel Ojeda // 66b437b383SMiguel Ojeda // For instance, a cast from `*const [T]` to `*const [U]` 67b437b383SMiguel Ojeda // preserves the number of elements. ... The same holds 68b437b383SMiguel Ojeda // for str and any compound type whose unsized tail is a 69b437b383SMiguel Ojeda // slice type, such as struct `Foo(i32, [u8])` or 70b437b383SMiguel Ojeda // `(u64, Foo)`. 71b437b383SMiguel Ojeda #[inline(always)] 72b437b383SMiguel Ojeda fn raw_from_ptr_len( 73b437b383SMiguel Ojeda bytes: #core::ptr::NonNull<u8>, 74b437b383SMiguel Ojeda meta: <Self as #zerocopy_crate::KnownLayout>::PointerMetadata, 75b437b383SMiguel Ojeda ) -> #core::ptr::NonNull<Self> { 76b437b383SMiguel Ojeda let trailing = <#trailing_field_ty as #zerocopy_crate::KnownLayout>::raw_from_ptr_len(bytes, meta); 77b437b383SMiguel Ojeda let slf = trailing.as_ptr() as *mut Self; 78b437b383SMiguel Ojeda // SAFETY: Constructed from `trailing`, which is non-null. 79b437b383SMiguel Ojeda unsafe { #core::ptr::NonNull::new_unchecked(slf) } 80b437b383SMiguel Ojeda } 81b437b383SMiguel Ojeda 82b437b383SMiguel Ojeda #[inline(always)] 83b437b383SMiguel Ojeda fn pointer_to_metadata(ptr: *mut Self) -> <Self as #zerocopy_crate::KnownLayout>::PointerMetadata { 84b437b383SMiguel Ojeda <#trailing_field_ty>::pointer_to_metadata(ptr as *mut _) 85b437b383SMiguel Ojeda } 86b437b383SMiguel Ojeda } 87b437b383SMiguel Ojeda }; 88b437b383SMiguel Ojeda 89b437b383SMiguel Ojeda let inner_extras = { 90b437b383SMiguel Ojeda let leading_fields_tys = leading_fields_tys.clone(); 91b437b383SMiguel Ojeda let methods = make_methods(*trailing_field_ty); 92b437b383SMiguel Ojeda let (_, ty_generics, _) = ctx.ast.generics.split_for_impl(); 93b437b383SMiguel Ojeda 94b437b383SMiguel Ojeda quote!( 95b437b383SMiguel Ojeda type PointerMetadata = <#trailing_field_ty as #zerocopy_crate::KnownLayout>::PointerMetadata; 96b437b383SMiguel Ojeda 97b437b383SMiguel Ojeda type MaybeUninit = __ZerocopyKnownLayoutMaybeUninit #ty_generics; 98b437b383SMiguel Ojeda 99b437b383SMiguel Ojeda // SAFETY: `LAYOUT` accurately describes the layout of `Self`. 100b437b383SMiguel Ojeda // The documentation of `DstLayout::for_repr_c_struct` vows that 101b437b383SMiguel Ojeda // invocations in this manner will accurately describe a type, 102b437b383SMiguel Ojeda // so long as: 103b437b383SMiguel Ojeda // 104b437b383SMiguel Ojeda // - that type is `repr(C)`, 105b437b383SMiguel Ojeda // - its fields are enumerated in the order they appear, 106b437b383SMiguel Ojeda // - the presence of `repr_align` and `repr_packed` are 107b437b383SMiguel Ojeda // correctly accounted for. 108b437b383SMiguel Ojeda // 109b437b383SMiguel Ojeda // We respect all three of these preconditions here. This 110b437b383SMiguel Ojeda // expansion is only used if `is_repr_c_struct`, we enumerate 111b437b383SMiguel Ojeda // the fields in order, and we extract the values of `align(N)` 112b437b383SMiguel Ojeda // and `packed(N)`. 113b437b383SMiguel Ojeda const LAYOUT: #zerocopy_crate::DstLayout = #zerocopy_crate::DstLayout::for_repr_c_struct( 114b437b383SMiguel Ojeda #repr_align, 115b437b383SMiguel Ojeda #repr_packed, 116b437b383SMiguel Ojeda &[ 117b437b383SMiguel Ojeda #(#zerocopy_crate::DstLayout::for_type::<#leading_fields_tys>(),)* 118b437b383SMiguel Ojeda <#trailing_field_ty as #zerocopy_crate::KnownLayout>::LAYOUT 119b437b383SMiguel Ojeda ], 120b437b383SMiguel Ojeda ); 121b437b383SMiguel Ojeda 122b437b383SMiguel Ojeda #methods 123b437b383SMiguel Ojeda ) 124b437b383SMiguel Ojeda }; 125b437b383SMiguel Ojeda 126b437b383SMiguel Ojeda let outer_extras = { 127b437b383SMiguel Ojeda let ident = &ctx.ast.ident; 128b437b383SMiguel Ojeda let vis = &ctx.ast.vis; 129b437b383SMiguel Ojeda let params = &ctx.ast.generics.params; 130b437b383SMiguel Ojeda let (impl_generics, ty_generics, where_clause) = ctx.ast.generics.split_for_impl(); 131b437b383SMiguel Ojeda 132b437b383SMiguel Ojeda let predicates = if let Some(where_clause) = where_clause { 133b437b383SMiguel Ojeda where_clause.predicates.clone() 134b437b383SMiguel Ojeda } else { 135b437b383SMiguel Ojeda Default::default() 136b437b383SMiguel Ojeda }; 137b437b383SMiguel Ojeda 138b437b383SMiguel Ojeda // Generate a valid ident for a type-level handle to a field of a 139b437b383SMiguel Ojeda // given `name`. 140b437b383SMiguel Ojeda let field_index = |name: &TokenStream| ident!(("__Zerocopy_Field_{}", name), ident.span()); 141b437b383SMiguel Ojeda 142b437b383SMiguel Ojeda let field_indices: Vec<_> = 143b437b383SMiguel Ojeda fields.iter().map(|(_vis, name, _ty)| field_index(name)).collect(); 144b437b383SMiguel Ojeda 145b437b383SMiguel Ojeda // Define the collection of type-level field handles. 146b437b383SMiguel Ojeda let field_defs = field_indices.iter().zip(fields).map(|(idx, (vis, _, _))| { 147b437b383SMiguel Ojeda quote! { 148b437b383SMiguel Ojeda #vis struct #idx; 149b437b383SMiguel Ojeda } 150b437b383SMiguel Ojeda }); 151b437b383SMiguel Ojeda 152b437b383SMiguel Ojeda let field_impls = field_indices.iter().zip(fields).map(|(idx, (_, _, ty))| quote! { 153b437b383SMiguel Ojeda // SAFETY: `#ty` is the type of `#ident`'s field at `#idx`. 154b437b383SMiguel Ojeda // 155b437b383SMiguel Ojeda // We implement `Field` for each field of the struct to create a 156b437b383SMiguel Ojeda // projection from the field index to its type. This allows us 157b437b383SMiguel Ojeda // to refer to the field's type in a way that respects `Self` 158b437b383SMiguel Ojeda // hygiene. If we just copy-pasted the tokens of `#ty`, we 159b437b383SMiguel Ojeda // would not respect `Self` hygiene, as `Self` would refer to 160b437b383SMiguel Ojeda // the helper struct we are generating, not the derive target 161b437b383SMiguel Ojeda // type. 162b437b383SMiguel Ojeda unsafe impl #impl_generics #zerocopy_crate::util::macro_util::Field<#idx> for #ident #ty_generics 163b437b383SMiguel Ojeda where 164b437b383SMiguel Ojeda #predicates 165b437b383SMiguel Ojeda { 166b437b383SMiguel Ojeda type Type = #ty; 167b437b383SMiguel Ojeda } 168b437b383SMiguel Ojeda }); 169b437b383SMiguel Ojeda 170b437b383SMiguel Ojeda let trailing_field_index = field_index(trailing_field_name); 171b437b383SMiguel Ojeda let leading_field_indices = 172b437b383SMiguel Ojeda leading_fields.iter().map(|(_vis, name, _ty)| field_index(name)); 173b437b383SMiguel Ojeda 174b437b383SMiguel Ojeda // We use `Field` to project the type of the trailing field. This is 175b437b383SMiguel Ojeda // required to ensure that if the field type uses `Self`, it 176b437b383SMiguel Ojeda // resolves to the derive target type, not the helper struct we are 177b437b383SMiguel Ojeda // generating. 178b437b383SMiguel Ojeda let trailing_field_ty = quote! { 179b437b383SMiguel Ojeda <#ident #ty_generics as 180b437b383SMiguel Ojeda #zerocopy_crate::util::macro_util::Field<#trailing_field_index> 181b437b383SMiguel Ojeda >::Type 182b437b383SMiguel Ojeda }; 183b437b383SMiguel Ojeda 184b437b383SMiguel Ojeda let methods = make_methods(&parse_quote! { 185b437b383SMiguel Ojeda <#trailing_field_ty as #zerocopy_crate::KnownLayout>::MaybeUninit 186b437b383SMiguel Ojeda }); 187b437b383SMiguel Ojeda 188b437b383SMiguel Ojeda let core = ctx.core_path(); 189b437b383SMiguel Ojeda 190b437b383SMiguel Ojeda quote! { 191b437b383SMiguel Ojeda #(#field_defs)* 192b437b383SMiguel Ojeda 193b437b383SMiguel Ojeda #(#field_impls)* 194b437b383SMiguel Ojeda 195b437b383SMiguel Ojeda // SAFETY: This has the same layout as the derive target type, 196b437b383SMiguel Ojeda // except that it admits uninit bytes. This is ensured by using 197b437b383SMiguel Ojeda // the same repr as the target type, and by using field types 198b437b383SMiguel Ojeda // which have the same layout as the target type's fields, 199b437b383SMiguel Ojeda // except that they admit uninit bytes. We indirect through 200b437b383SMiguel Ojeda // `Field` to ensure that occurrences of `Self` resolve to 201b437b383SMiguel Ojeda // `#ty`, not `__ZerocopyKnownLayoutMaybeUninit` (see #2116). 202b437b383SMiguel Ojeda #repr 203b437b383SMiguel Ojeda #[doc(hidden)] 204b437b383SMiguel Ojeda #vis struct __ZerocopyKnownLayoutMaybeUninit<#params> ( 205b437b383SMiguel Ojeda #(#core::mem::MaybeUninit< 206b437b383SMiguel Ojeda <#ident #ty_generics as 207b437b383SMiguel Ojeda #zerocopy_crate::util::macro_util::Field<#leading_field_indices> 208b437b383SMiguel Ojeda >::Type 209b437b383SMiguel Ojeda >,)* 210b437b383SMiguel Ojeda // NOTE(#2302): We wrap in `ManuallyDrop` here in case the 211b437b383SMiguel Ojeda // type we're operating on is both generic and 212b437b383SMiguel Ojeda // `repr(packed)`. In that case, Rust needs to know that the 213b437b383SMiguel Ojeda // type is *either* `Sized` or has a trivial `Drop`. 214b437b383SMiguel Ojeda // `ManuallyDrop` has a trivial `Drop`, and so satisfies 215b437b383SMiguel Ojeda // this requirement. 216b437b383SMiguel Ojeda #core::mem::ManuallyDrop< 217b437b383SMiguel Ojeda <#trailing_field_ty as #zerocopy_crate::KnownLayout>::MaybeUninit 218b437b383SMiguel Ojeda > 219b437b383SMiguel Ojeda ) 220b437b383SMiguel Ojeda where 221b437b383SMiguel Ojeda #trailing_field_ty: #zerocopy_crate::KnownLayout, 222b437b383SMiguel Ojeda #predicates; 223b437b383SMiguel Ojeda 224b437b383SMiguel Ojeda // SAFETY: We largely defer to the `KnownLayout` implementation 225b437b383SMiguel Ojeda // on the derive target type (both by using the same tokens, and 226b437b383SMiguel Ojeda // by deferring to impl via type-level indirection). This is 227b437b383SMiguel Ojeda // sound, since `__ZerocopyKnownLayoutMaybeUninit` is guaranteed 228b437b383SMiguel Ojeda // to have the same layout as the derive target type, except 229b437b383SMiguel Ojeda // that `__ZerocopyKnownLayoutMaybeUninit` admits uninit bytes. 230b437b383SMiguel Ojeda unsafe impl #impl_generics #zerocopy_crate::KnownLayout for __ZerocopyKnownLayoutMaybeUninit #ty_generics 231b437b383SMiguel Ojeda where 232b437b383SMiguel Ojeda #trailing_field_ty: #zerocopy_crate::KnownLayout, 233b437b383SMiguel Ojeda #predicates 234b437b383SMiguel Ojeda { 235b437b383SMiguel Ojeda fn only_derive_is_allowed_to_implement_this_trait() {} 236b437b383SMiguel Ojeda 237b437b383SMiguel Ojeda type PointerMetadata = <#ident #ty_generics as #zerocopy_crate::KnownLayout>::PointerMetadata; 238b437b383SMiguel Ojeda 239b437b383SMiguel Ojeda type MaybeUninit = Self; 240b437b383SMiguel Ojeda 241b437b383SMiguel Ojeda const LAYOUT: #zerocopy_crate::DstLayout = <#ident #ty_generics as #zerocopy_crate::KnownLayout>::LAYOUT; 242b437b383SMiguel Ojeda 243b437b383SMiguel Ojeda #methods 244b437b383SMiguel Ojeda } 245b437b383SMiguel Ojeda } 246b437b383SMiguel Ojeda }; 247b437b383SMiguel Ojeda 248b437b383SMiguel Ojeda Some((SelfBounds::None, inner_extras, Some(outer_extras))) 249b437b383SMiguel Ojeda } 250b437b383SMiguel Ojeda 251b437b383SMiguel Ojeda pub(crate) fn derive(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> { 252b437b383SMiguel Ojeda // If this is a `repr(C)` struct, then `c_struct_repr` contains the entire 253b437b383SMiguel Ojeda // `repr` attribute. 254b437b383SMiguel Ojeda let c_struct_repr = match &ctx.ast.data { 255b437b383SMiguel Ojeda Data::Struct(..) => { 256b437b383SMiguel Ojeda let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?; 257b437b383SMiguel Ojeda if repr.is_c() { 258b437b383SMiguel Ojeda Some(repr) 259b437b383SMiguel Ojeda } else { 260b437b383SMiguel Ojeda None 261b437b383SMiguel Ojeda } 262b437b383SMiguel Ojeda } 263b437b383SMiguel Ojeda Data::Enum(..) | Data::Union(..) => None, 264b437b383SMiguel Ojeda }; 265b437b383SMiguel Ojeda 266b437b383SMiguel Ojeda let fields = ctx.ast.data.fields(); 267b437b383SMiguel Ojeda 268b437b383SMiguel Ojeda let (self_bounds, inner_extras, outer_extras) = c_struct_repr 269b437b383SMiguel Ojeda .as_ref() 270b437b383SMiguel Ojeda .and_then(|repr| { 271b437b383SMiguel Ojeda derive_known_layout_for_repr_c_struct(ctx, repr, &fields) 272b437b383SMiguel Ojeda }) 273b437b383SMiguel Ojeda .unwrap_or_else(|| { 274b437b383SMiguel Ojeda let zerocopy_crate = &ctx.zerocopy_crate; 275b437b383SMiguel Ojeda let core = ctx.core_path(); 276b437b383SMiguel Ojeda 277b437b383SMiguel Ojeda // For enums, unions, and non-`repr(C)` structs, we require that 278b437b383SMiguel Ojeda // `Self` is sized, and as a result don't need to reason about the 279b437b383SMiguel Ojeda // internals of the type. 280b437b383SMiguel Ojeda ( 281b437b383SMiguel Ojeda SelfBounds::SIZED, 282b437b383SMiguel Ojeda quote!( 283b437b383SMiguel Ojeda type PointerMetadata = (); 284b437b383SMiguel Ojeda type MaybeUninit = 285b437b383SMiguel Ojeda #core::mem::MaybeUninit<Self>; 286b437b383SMiguel Ojeda 287b437b383SMiguel Ojeda // SAFETY: `LAYOUT` is guaranteed to accurately describe the 288b437b383SMiguel Ojeda // layout of `Self`, because that is the documented safety 289b437b383SMiguel Ojeda // contract of `DstLayout::for_type`. 290b437b383SMiguel Ojeda const LAYOUT: #zerocopy_crate::DstLayout = #zerocopy_crate::DstLayout::for_type::<Self>(); 291b437b383SMiguel Ojeda 292b437b383SMiguel Ojeda // SAFETY: `.cast` preserves address and provenance. 293b437b383SMiguel Ojeda // 294b437b383SMiguel Ojeda // FIXME(#429): Add documentation to `.cast` that promises that 295b437b383SMiguel Ojeda // it preserves provenance. 296b437b383SMiguel Ojeda #[inline(always)] 297b437b383SMiguel Ojeda fn raw_from_ptr_len(bytes: #core::ptr::NonNull<u8>, _meta: ()) -> #core::ptr::NonNull<Self> { 298b437b383SMiguel Ojeda bytes.cast::<Self>() 299b437b383SMiguel Ojeda } 300b437b383SMiguel Ojeda 301b437b383SMiguel Ojeda #[inline(always)] 302b437b383SMiguel Ojeda fn pointer_to_metadata(_ptr: *mut Self) -> () {} 303b437b383SMiguel Ojeda ), 304b437b383SMiguel Ojeda None, 305b437b383SMiguel Ojeda ) 306b437b383SMiguel Ojeda }); 307b437b383SMiguel Ojeda Ok(match &ctx.ast.data { 308b437b383SMiguel Ojeda Data::Struct(strct) => { 309b437b383SMiguel Ojeda let require_trait_bound_on_field_types = 310b437b383SMiguel Ojeda if matches!(self_bounds, SelfBounds::All(&[Trait::Sized])) { 311b437b383SMiguel Ojeda FieldBounds::None 312b437b383SMiguel Ojeda } else { 313b437b383SMiguel Ojeda FieldBounds::TRAILING_SELF 314b437b383SMiguel Ojeda }; 315b437b383SMiguel Ojeda 316b437b383SMiguel Ojeda // A bound on the trailing field is required, since structs are 317b437b383SMiguel Ojeda // unsized if their trailing field is unsized. Reflecting the layout 318b437b383SMiguel Ojeda // of an usized trailing field requires that the field is 319b437b383SMiguel Ojeda // `KnownLayout`. 320b437b383SMiguel Ojeda ImplBlockBuilder::new( 321b437b383SMiguel Ojeda ctx, 322b437b383SMiguel Ojeda strct, 323b437b383SMiguel Ojeda Trait::KnownLayout, 324b437b383SMiguel Ojeda require_trait_bound_on_field_types, 325b437b383SMiguel Ojeda ) 326b437b383SMiguel Ojeda .self_type_trait_bounds(self_bounds) 327b437b383SMiguel Ojeda .inner_extras(inner_extras) 328b437b383SMiguel Ojeda .outer_extras(outer_extras) 329b437b383SMiguel Ojeda .build() 330b437b383SMiguel Ojeda } 331b437b383SMiguel Ojeda Data::Enum(enm) => { 332b437b383SMiguel Ojeda // A bound on the trailing field is not required, since enums cannot 333b437b383SMiguel Ojeda // currently be unsized. 334b437b383SMiguel Ojeda ImplBlockBuilder::new(ctx, enm, Trait::KnownLayout, FieldBounds::None) 335b437b383SMiguel Ojeda .self_type_trait_bounds(SelfBounds::SIZED) 336b437b383SMiguel Ojeda .inner_extras(inner_extras) 337b437b383SMiguel Ojeda .outer_extras(outer_extras) 338b437b383SMiguel Ojeda .build() 339b437b383SMiguel Ojeda } 340b437b383SMiguel Ojeda Data::Union(unn) => { 341b437b383SMiguel Ojeda // A bound on the trailing field is not required, since unions 342b437b383SMiguel Ojeda // cannot currently be unsized. 343b437b383SMiguel Ojeda ImplBlockBuilder::new(ctx, unn, Trait::KnownLayout, FieldBounds::None) 344b437b383SMiguel Ojeda .self_type_trait_bounds(SelfBounds::SIZED) 345b437b383SMiguel Ojeda .inner_extras(inner_extras) 346b437b383SMiguel Ojeda .outer_extras(outer_extras) 347b437b383SMiguel Ojeda .build() 348b437b383SMiguel Ojeda } 349b437b383SMiguel Ojeda }) 350b437b383SMiguel Ojeda } 351