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