@@ -755,10 +755,10 @@ declare_lint! {
755755 /// *subsequent* fields of the associated structs to use an alignment value
756756 /// where the floating-point type is aligned on a 4-byte boundary.
757757 ///
758- /// The power alignment rule for structs needed for C compatibility is
759- /// unimplementable within `repr(C)` in the compiler without building in
760- /// handling of references to packed fields and infectious nested layouts,
761- /// so a warning is produced in these situations .
758+ /// Effectively, subsequent floating-point fields act as-if they are `repr(packed(4))`. This
759+ /// would be unsound to do in a `repr(C)` type without all the restrictions that come with
760+ /// `repr(packed)`. Rust instead chooses a layout that maintains soundness of Rust code, at the
761+ /// expense of incompatibility with C code .
762762 ///
763763 /// ### Example
764764 ///
@@ -790,8 +790,10 @@ declare_lint! {
790790 /// - offset_of!(Floats, a) == 0
791791 /// - offset_of!(Floats, b) == 8
792792 /// - offset_of!(Floats, c) == 12
793- /// However, rust currently aligns `c` at offset_of!(Floats, c) == 16.
794- /// Thus, a warning should be produced for the above struct in this case.
793+ ///
794+ /// However, Rust currently aligns `c` at `offset_of!(Floats, c) == 16`.
795+ /// Using offset 12 would be unsound since `f64` generally must be 8-aligned on this target.
796+ /// Thus, a warning is produced for the above struct.
795797 USES_POWER_ALIGNMENT ,
796798 Warn ,
797799 "Structs do not follow the power alignment rule under repr(C)"
@@ -1655,15 +1657,13 @@ impl ImproperCTypesDefinitions {
16551657 cx : & LateContext < ' tcx > ,
16561658 ty : Ty < ' tcx > ,
16571659 ) -> bool {
1660+ assert ! ( cx. tcx. sess. target. os == "aix" ) ;
16581661 // Structs (under repr(C)) follow the power alignment rule if:
16591662 // - the first field of the struct is a floating-point type that
16601663 // is greater than 4-bytes, or
16611664 // - the first field of the struct is an aggregate whose
16621665 // recursively first field is a floating-point type greater than
16631666 // 4 bytes.
1664- if cx. tcx . sess . target . os != "aix" {
1665- return false ;
1666- }
16671667 if ty. is_floating_point ( ) && ty. primitive_size ( cx. tcx ) . bytes ( ) > 4 {
16681668 return true ;
16691669 } else if let Adt ( adt_def, _) = ty. kind ( )
@@ -1701,21 +1701,14 @@ impl ImproperCTypesDefinitions {
17011701 && !adt_def. all_fields ( ) . next ( ) . is_none ( )
17021702 {
17031703 let struct_variant_data = item. expect_struct ( ) . 1 ;
1704- for ( index , .. ) in struct_variant_data. fields ( ) . iter ( ) . enumerate ( ) {
1704+ for field_def in struct_variant_data. fields ( ) . iter ( ) . skip ( 1 ) {
17051705 // Struct fields (after the first field) are checked for the
17061706 // power alignment rule, as fields after the first are likely
17071707 // to be the fields that are misaligned.
1708- if index != 0 {
1709- let first_field_def = struct_variant_data. fields ( ) [ index] ;
1710- let def_id = first_field_def. def_id ;
1711- let ty = cx. tcx . type_of ( def_id) . instantiate_identity ( ) ;
1712- if self . check_arg_for_power_alignment ( cx, ty) {
1713- cx. emit_span_lint (
1714- USES_POWER_ALIGNMENT ,
1715- first_field_def. span ,
1716- UsesPowerAlignment ,
1717- ) ;
1718- }
1708+ let def_id = field_def. def_id ;
1709+ let ty = cx. tcx . type_of ( def_id) . instantiate_identity ( ) ;
1710+ if self . check_arg_for_power_alignment ( cx, ty) {
1711+ cx. emit_span_lint ( USES_POWER_ALIGNMENT , field_def. span , UsesPowerAlignment ) ;
17191712 }
17201713 }
17211714 }
0 commit comments