@@ -114,24 +114,20 @@ impl<'a> StructLayoutTracker<'a> {
114114 }
115115 }
116116
117- pub ( crate ) fn saw_bitfield_unit ( & mut self , layout : Layout ) {
118- debug ! ( "saw bitfield unit for {}: {layout:?}" , self . name) ;
119-
120- self . latest_offset += layout. size ;
121-
117+ /// Returns a padding field if necessary for a given bitfield unit _before_ adding that unit.
118+ pub ( crate ) fn saw_bitfield_unit (
119+ & mut self ,
120+ layout : Layout ,
121+ offset : Option < usize > ,
122+ ) -> Option < proc_macro2:: TokenStream > {
122123 debug ! (
123- "Offset: <bitfield>: {} -> {}" ,
124- self . latest_offset - layout. size,
125- self . latest_offset
124+ "saw bitfield unit for {}: {layout:?} at {offset:?}" ,
125+ self . name
126126 ) ;
127-
128- self . latest_field_layout = Some ( layout) ;
129- self . last_field_was_bitfield = true ;
130- self . max_field_align = cmp:: max ( self . max_field_align , layout. align ) ;
127+ self . pad_to_offset ( layout, offset, /* is_bitfield = */ true )
131128 }
132129
133- /// Returns a padding field if necessary for a given new field _before_
134- /// adding that field.
130+ /// Returns a padding field if necessary for a given new field _before_ adding that field.
135131 pub ( crate ) fn saw_field (
136132 & mut self ,
137133 field_name : & str ,
@@ -147,9 +143,23 @@ impl<'a> StructLayoutTracker<'a> {
147143 field_name : & str ,
148144 field_layout : Layout ,
149145 field_offset : Option < usize > ,
146+ ) -> Option < proc_macro2:: TokenStream > {
147+ debug ! ( "saw_field_with_layout({field_name}, offset = {field_offset:?}, layout = {field_layout:?}" ) ;
148+ self . pad_to_offset (
149+ field_layout,
150+ field_offset,
151+ /* is_bitfield = */ false ,
152+ )
153+ }
154+
155+ fn pad_to_offset (
156+ & mut self ,
157+ field_layout : Layout ,
158+ field_offset : Option < usize > ,
159+ is_bitfield : bool ,
150160 ) -> Option < proc_macro2:: TokenStream > {
151161 let will_merge_with_bitfield =
152- self . will_merge_with_bitfield ( field_layout) ;
162+ !is_bitfield && self . will_merge_with_bitfield ( field_layout) ;
153163
154164 let is_union = self . comp . is_union ( ) ;
155165 let padding_bytes = match field_offset {
@@ -177,7 +187,9 @@ impl<'a> StructLayoutTracker<'a> {
177187
178188 self . latest_offset += padding_bytes;
179189
180- let padding_layout = if self . is_packed || is_union {
190+ // Bitfield units are always byte-aligned, so packed(N) can't move them into place like it
191+ // does for regular fields.
192+ let padding_layout = if ( self . is_packed && !is_bitfield) || is_union {
181193 None
182194 } else {
183195 let force_padding = self . ctx . options ( ) . force_explicit_padding ;
@@ -193,7 +205,7 @@ impl<'a> StructLayoutTracker<'a> {
193205 ) ;
194206
195207 debug ! (
196- "align field {field_name} to {}/{} with {padding_bytes} padding bytes {field_layout:?}" ,
208+ "align field to {}/{} with {padding_bytes} padding bytes {field_layout:?}" ,
197209 self . latest_offset,
198210 field_offset. unwrap_or( 0 ) / 8 ,
199211 ) ;
@@ -215,10 +227,10 @@ impl<'a> StructLayoutTracker<'a> {
215227 self . latest_field_layout = Some ( field_layout) ;
216228 self . max_field_align =
217229 cmp:: max ( self . max_field_align , field_layout. align ) ;
218- self . last_field_was_bitfield = false ;
230+ self . last_field_was_bitfield = is_bitfield ;
219231
220232 debug ! (
221- "Offset: {field_name}: { } -> {}" ,
233+ "Offset: {} -> {}" ,
222234 self . latest_offset - field_layout. size,
223235 self . latest_offset
224236 ) ;
0 commit comments