@@ -2009,32 +2009,39 @@ impl CodeGenerator for CompInfo {
20092009 let mut needs_default_impl = false ;
20102010 let mut needs_debug_impl = false ;
20112011 let mut needs_partialeq_impl = false ;
2012+ let mut needs_packed_wrapper = false ;
20122013 if let Some ( comment) = item. comment ( ctx) {
20132014 attributes. push ( attributes:: doc ( comment) ) ;
20142015 }
2016+
2017+ // We can't specify both packed(N) and align(N), but the packed()
2018+ // should be redundant in this case.
20152019 if packed && !is_opaque {
20162020 let n = layout. map_or ( 1 , |l| l. align ) ;
20172021 assert ! ( ctx. options( ) . rust_features( ) . repr_packed_n || n == 1 ) ;
2018- let packed_repr = if n == 1 {
2022+ if ctx. options ( ) . rust_features ( ) . repr_align &&
2023+ explicit_align. is_some ( )
2024+ {
2025+ needs_packed_wrapper = true ;
2026+ }
2027+ let packed_repr = if n == 1 || needs_packed_wrapper {
20192028 "packed" . to_string ( )
20202029 } else {
20212030 format ! ( "packed({})" , n)
20222031 } ;
20232032 attributes. push ( attributes:: repr_list ( & [ "C" , & packed_repr] ) ) ;
20242033 } else {
20252034 attributes. push ( attributes:: repr ( "C" ) ) ;
2026- }
20272035
2028- if ctx. options ( ) . rust_features ( ) . repr_align && !packed {
2029- // We can't specify both packed(N) and align(N), but the align()
2030- // should be redundant in this case.
2031- if let Some ( explicit) = explicit_align {
2032- // Ensure that the struct has the correct alignment even in
2033- // presence of alignas.
2034- let explicit = helpers:: ast_ty:: int_expr ( explicit as i64 ) ;
2035- attributes. push ( quote ! {
2036- #[ repr( align( #explicit) ) ]
2037- } ) ;
2036+ if ctx. options ( ) . rust_features ( ) . repr_align {
2037+ if let Some ( explicit) = explicit_align {
2038+ // Ensure that the struct has the correct alignment even in
2039+ // presence of alignas.
2040+ let explicit = helpers:: ast_ty:: int_expr ( explicit as i64 ) ;
2041+ attributes. push ( quote ! {
2042+ #[ repr( align( #explicit) ) ]
2043+ } ) ;
2044+ }
20382045 }
20392046 }
20402047
@@ -2088,15 +2095,21 @@ impl CodeGenerator for CompInfo {
20882095 attributes. push ( attributes:: must_use ( ) ) ;
20892096 }
20902097
2098+ let layout_ident = if needs_packed_wrapper {
2099+ ctx. rust_ident ( canonical_name. to_owned ( ) + "__packed" )
2100+ } else {
2101+ canonical_ident. clone ( )
2102+ } ;
2103+
20912104 let mut tokens = if is_union && struct_layout. is_rust_union ( ) {
20922105 quote ! {
20932106 #( #attributes ) *
2094- pub union #canonical_ident
2107+ pub union #layout_ident
20952108 }
20962109 } else {
20972110 quote ! {
20982111 #( #attributes ) *
2099- pub struct #canonical_ident
2112+ pub struct #layout_ident
21002113 }
21012114 } ;
21022115
@@ -2107,6 +2120,19 @@ impl CodeGenerator for CompInfo {
21072120 } ) ;
21082121 result. push ( tokens) ;
21092122
2123+ if needs_packed_wrapper {
2124+ let attributes = attributes:: derives ( & derives) ;
2125+ let align = proc_macro2:: TokenStream :: from_str (
2126+ & explicit_align. unwrap ( ) . to_string ( ) ,
2127+ )
2128+ . unwrap ( ) ;
2129+ result. push ( quote ! {
2130+ #attributes
2131+ #[ repr( C , align( #align) ) ]
2132+ pub struct #canonical_ident( pub #layout_ident) ;
2133+ } ) ;
2134+ }
2135+
21102136 // Generate the inner types and all that stuff.
21112137 //
21122138 // TODO: In the future we might want to be smart, and use nested
@@ -2206,12 +2232,17 @@ impl CodeGenerator for CompInfo {
22062232 let uninit_decl = if !check_field_offset. is_empty ( ) {
22072233 // FIXME: When MSRV >= 1.59.0, we can use
22082234 // > const PTR: *const #canonical_ident = ::#prefix::mem::MaybeUninit::uninit().as_ptr();
2235+ let layout_cast = if needs_packed_wrapper {
2236+ Some ( quote ! ( as * const #layout_ident) )
2237+ } else {
2238+ None
2239+ } ;
22092240 Some ( quote ! {
22102241 // Use a shared MaybeUninit so that rustc with
22112242 // opt-level=0 doesn't take too much stack space,
22122243 // see #2218.
22132244 const UNINIT : :: #prefix:: mem:: MaybeUninit <#canonical_ident> = :: #prefix:: mem:: MaybeUninit :: uninit( ) ;
2214- let ptr = UNINIT . as_ptr( ) ;
2245+ let ptr = UNINIT . as_ptr( ) #layout_cast ;
22152246 } )
22162247 } else {
22172248 None
0 commit comments