@@ -249,10 +249,6 @@ fn init_fields(
249249 } ) ;
250250 // Again span for better diagnostics
251251 let write = quote_spanned ! ( ident. span( ) => :: core:: ptr:: write) ;
252- // NOTE: the field accessor ensures that the initialized field is properly aligned.
253- // Unaligned fields will cause the compiler to emit E0793. We do not support
254- // unaligned fields since `Init::__init` requires an aligned pointer; the call to
255- // `ptr::write` below has the same requirement.
256252 let accessor = if pinned {
257253 let project_ident = format_ident ! ( "__project_{ident}" ) ;
258254 quote ! {
@@ -367,49 +363,49 @@ fn init_fields(
367363 }
368364}
369365
370- /// Generate the check for ensuring that every field has been initialized.
366+ /// Generate the check for ensuring that every field has been initialized and aligned .
371367fn make_field_check (
372368 fields : & Punctuated < InitializerField , Token ! [ , ] > ,
373369 init_kind : InitKind ,
374370 path : & Path ,
375371) -> TokenStream {
376- let field_attrs = fields
372+ let field_attrs: Vec < _ > = fields
377373 . iter ( )
378- . filter_map ( |f| f. kind . ident ( ) . map ( |_| & f. attrs ) ) ;
379- let field_name = fields . iter ( ) . filter_map ( |f| f . kind . ident ( ) ) ;
380- match init_kind {
381- InitKind :: Normal => quote ! {
382- // We use unreachable code to ensure that all fields have been mentioned exactly once ,
383- // this struct initializer will still be type-checked and complain with a very natural
384- // error message if a field is forgotten/mentioned more than once.
385- # [ allow ( unreachable_code , clippy :: diverging_sub_expression ) ]
386- // SAFETY: this code is never executed.
387- let _ = || unsafe {
388- :: core :: ptr :: write ( slot , #path {
389- # (
390- # ( #field_attrs ) *
391- #field_name : :: core :: panic! ( ) ,
392- ) *
393- } )
394- } ;
395- } ,
396- InitKind :: Zeroing => quote ! {
397- // We use unreachable code to ensure that all fields have been mentioned at most once.
398- // Since the user specified `..Zeroable::zeroed()` at the end, all missing fields will
399- // be zeroed. This struct initializer will still be type-checked and complain with a
400- // very natural error message if a field is mentioned more than once, or doesn't exist.
401- # [ allow ( unreachable_code , clippy :: diverging_sub_expression , unused_assignments ) ]
402- // SAFETY: this code is never executed.
403- let _ = || unsafe {
404- :: core :: ptr :: write ( slot , #path {
405- # (
406- # ( #field_attrs ) *
407- #field_name : :: core :: panic! ( ) ,
408- ) *
409- .. :: core :: mem :: zeroed ( )
410- } )
411- } ;
412- } ,
374+ . filter_map ( |f| f. kind . ident ( ) . map ( |_| & f. attrs ) )
375+ . collect ( ) ;
376+ let field_name : Vec < _ > = fields . iter ( ) . filter_map ( |f| f . kind . ident ( ) ) . collect ( ) ;
377+ let zeroing_trailer = match init_kind {
378+ InitKind :: Normal => None ,
379+ InitKind :: Zeroing => Some ( quote ! {
380+ .. :: core :: mem :: zeroed ( )
381+ } ) ,
382+ } ;
383+ quote ! {
384+ # [ allow ( unreachable_code , clippy :: diverging_sub_expression ) ]
385+ // We use unreachable code to perform field checks. They're still checked by the compiler.
386+ // SAFETY: this code is never executed.
387+ let _ = || unsafe {
388+ // Create references to ensure that the initialized field is properly aligned.
389+ // Unaligned fields will cause the compiler to emit E0793. We do not support
390+ // unaligned fields since `Init::__init` requires an aligned pointer; the call to
391+ // `ptr::write` for value-initialization case has the same requirement.
392+ # (
393+ # ( #field_attrs ) *
394+ let _ = & ( * slot ) . #field_name ;
395+ ) *
396+
397+ // If the zeroing trailer is not present, this checks that all fields have been
398+ // mentioned exactly once. If the zeroing trailer is present, all missing fields will be
399+ // zeroed, so this checks that all fields have been mentioned at most once. The use of
400+ // struct initializer will still generate very natural error messages for any misuse.
401+ :: core :: ptr :: write ( slot , #path {
402+ # (
403+ # ( #field_attrs ) *
404+ #field_name : :: core :: panic! ( ) ,
405+ ) *
406+ #zeroing_trailer
407+ } )
408+ } ;
413409 }
414410}
415411
0 commit comments