xref: /linux/rust/zerocopy-derive/derive/known_layout.rs (revision b079329b8691768962aa514b8f8c9077ca352459)
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