@@ -144,8 +144,8 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result<Tok
144144 Some ( ( trailing_field, leading_fields) ) ,
145145 ) = ( is_repr_c_struct, fields. split_last ( ) )
146146 {
147- let ( _name , trailing_field_ty) = trailing_field;
148- let leading_fields_tys = leading_fields. iter ( ) . map ( |( _name, ty) | ty) ;
147+ let ( _vis , trailing_field_name , trailing_field_ty) = trailing_field;
148+ let leading_fields_tys = leading_fields. iter ( ) . map ( |( _vis , _name, ty) | ty) ;
149149
150150 let core_path = quote ! ( :: zerocopy:: util:: macro_util:: core_reexport) ;
151151 let repr_align = repr
@@ -266,20 +266,66 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result<Tok
266266 Default :: default ( )
267267 } ;
268268
269+ // Generate a valid ident for a type-level handle to a field of a
270+ // given `name`.
271+ let field_index =
272+ |name| Ident :: new ( & format ! ( "__Zerocopy_Field_{}" , name) , ident. span ( ) ) ;
273+
274+ let field_indices: Vec < _ > =
275+ fields. iter ( ) . map ( |( _vis, name, _ty) | field_index ( name) ) . collect ( ) ;
276+
277+ // Define the collection of type-level field handles.
278+ let field_defs = field_indices. iter ( ) . zip ( & fields) . map ( |( idx, ( vis, _, _) ) | {
279+ quote ! {
280+ #[ allow( non_camel_case_types) ]
281+ #vis struct #idx;
282+ }
283+ } ) ;
284+
285+ let field_impls = field_indices. iter ( ) . zip ( & fields) . map ( |( idx, ( _, _, ty) ) | quote ! {
286+ // SAFETY: `#ty` is the type of `#ident`'s field at `#idx`.
287+ unsafe impl #impl_generics :: zerocopy:: util:: macro_util:: Field <#idx> for #ident #ty_generics
288+ where
289+ #predicates
290+ {
291+ type Type = #ty;
292+ }
293+ } ) ;
294+
295+ let trailing_field_index = field_index ( trailing_field_name) ;
296+ let leading_field_indices =
297+ leading_fields. iter ( ) . map ( |( _vis, name, _ty) | field_index ( name) ) ;
298+
299+ let trailing_field_ty = quote ! {
300+ <#ident #ty_generics as
301+ :: zerocopy:: util:: macro_util:: Field <#trailing_field_index>
302+ >:: Type
303+ } ;
304+
269305 let methods = make_methods ( & parse_quote ! {
270306 <#trailing_field_ty as :: zerocopy:: KnownLayout >:: MaybeUninit
271307 } ) ;
272308
273309 quote ! {
310+ #( #field_defs) *
311+
312+ #( #field_impls) *
313+
274314 // SAFETY: This has the same layout as the derive target type,
275- // except that it admits uninit bytes. This is ensured by using the
276- // same repr as the target type, and by using field types which have
277- // the same layout as the target type's fields, except that they
278- // admit uninit bytes.
315+ // except that it admits uninit bytes. This is ensured by using
316+ // the same repr as the target type, and by using field types
317+ // which have the same layout as the target type's fields,
318+ // except that they admit uninit bytes. We indirect through
319+ // `Field` to ensure that occurrences of `Self` resolve to
320+ // `#ty`, not `__ZerocopyKnownLayoutMaybeUninit` (see #2116).
279321 #repr
280322 #[ doc( hidden) ]
281323 #vis struct __ZerocopyKnownLayoutMaybeUninit<#params> (
282- #( :: zerocopy:: util:: macro_util:: core_reexport:: mem:: MaybeUninit <#leading_fields_tys>, ) *
324+ #( :: zerocopy:: util:: macro_util:: core_reexport:: mem:: MaybeUninit <
325+ <#ident #ty_generics as
326+ :: zerocopy:: util:: macro_util:: Field <#leading_field_indices>
327+ >:: Type
328+ >, ) *
283329 <#trailing_field_ty as :: zerocopy:: KnownLayout >:: MaybeUninit
284330 )
285331 where
@@ -295,9 +341,6 @@ fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result<Tok
295341 unsafe impl #impl_generics :: zerocopy:: KnownLayout for __ZerocopyKnownLayoutMaybeUninit #ty_generics
296342 where
297343 #trailing_field_ty: :: zerocopy:: KnownLayout ,
298- // This bound may appear to be superfluous, but is required
299- // on our MSRV (1.55) to avoid an ICE.
300- <#trailing_field_ty as :: zerocopy:: KnownLayout >:: MaybeUninit : :: zerocopy:: KnownLayout ,
301344 #predicates
302345 {
303346 #[ allow( clippy:: missing_inline_in_public_items) ]
@@ -494,8 +537,8 @@ fn derive_try_from_bytes_struct(
494537) -> Result < TokenStream , Error > {
495538 let extras = try_gen_trivial_is_bit_valid ( ast, top_level) . unwrap_or_else ( || {
496539 let fields = strct. fields ( ) ;
497- let field_names = fields. iter ( ) . map ( |( name, _ty) | name) ;
498- let field_tys = fields. iter ( ) . map ( |( _name, ty) | ty) ;
540+ let field_names = fields. iter ( ) . map ( |( _vis , name, _ty) | name) ;
541+ let field_tys = fields. iter ( ) . map ( |( _vis , _name, ty) | ty) ;
499542 quote ! (
500543 // SAFETY: We use `is_bit_valid` to validate that each field is
501544 // bit-valid, and only return `true` if all of them are. The bit
@@ -552,8 +595,8 @@ fn derive_try_from_bytes_union(
552595 FieldBounds :: All ( & [ TraitBound :: Slf , TraitBound :: Other ( Trait :: Immutable ) ] ) ;
553596 let extras = try_gen_trivial_is_bit_valid ( ast, top_level) . unwrap_or_else ( || {
554597 let fields = unn. fields ( ) ;
555- let field_names = fields. iter ( ) . map ( |( name, _ty) | name) ;
556- let field_tys = fields. iter ( ) . map ( |( _name, ty) | ty) ;
598+ let field_names = fields. iter ( ) . map ( |( _vis , name, _ty) | name) ;
599+ let field_tys = fields. iter ( ) . map ( |( _vis , _name, ty) | ty) ;
557600 quote ! (
558601 // SAFETY: We use `is_bit_valid` to validate that any field is
559602 // bit-valid; we only return `true` if at least one of them is. The
@@ -1419,12 +1462,13 @@ fn impl_block<D: DataExt>(
14191462 parse_quote ! ( #ty: #( #traits) +* )
14201463 }
14211464 let field_type_bounds: Vec < _ > = match ( field_type_trait_bounds, & fields[ ..] ) {
1422- ( FieldBounds :: All ( traits) , _) => {
1423- fields. iter ( ) . map ( |( _name, ty) | bound_tt ( ty, normalize_bounds ( trt, traits) ) ) . collect ( )
1424- }
1465+ ( FieldBounds :: All ( traits) , _) => fields
1466+ . iter ( )
1467+ . map ( |( _vis, _name, ty) | bound_tt ( ty, normalize_bounds ( trt, traits) ) )
1468+ . collect ( ) ,
14251469 ( FieldBounds :: None , _) | ( FieldBounds :: Trailing ( ..) , [ ] ) => vec ! [ ] ,
14261470 ( FieldBounds :: Trailing ( traits) , [ .., last] ) => {
1427- vec ! [ bound_tt( last. 1 , normalize_bounds( trt, traits) ) ]
1471+ vec ! [ bound_tt( last. 2 , normalize_bounds( trt, traits) ) ]
14281472 }
14291473 ( FieldBounds :: Explicit ( bounds) , _) => bounds,
14301474 } ;
@@ -1436,7 +1480,7 @@ fn impl_block<D: DataExt>(
14361480 let padding_check_bound =
14371481 padding_check. and_then ( |check| ( !fields. is_empty ( ) ) . then_some ( check) ) . map ( |check| {
14381482 let variant_types = variants. iter ( ) . map ( |var| {
1439- let types = var. iter ( ) . map ( |( _name, ty) | ty) ;
1483+ let types = var. iter ( ) . map ( |( _vis , _name, ty) | ty) ;
14401484 quote ! ( [ #( #types) , * ] )
14411485 } ) ;
14421486 let validator_context = check. validator_macro_context ( ) ;
0 commit comments