@@ -755,18 +755,26 @@ declare_lint! {
755755 /// recursively first field (as in "at offset 0") modify the layout of
756756 /// *subsequent* fields of the associated structs to use an alignment value
757757 /// where the floating-point type is aligned on a 4-byte boundary.
758+ /// This affects nested structs as well.
758759 ///
759- /// Effectively, subsequent floating-point fields act as-if they are `repr(packed(4))`. This
760- /// would be unsound to do in a `repr(C)` type without all the restrictions that come with
761- /// `repr(packed)`. Rust instead chooses a layout that maintains soundness of Rust code, at the
762- /// expense of incompatibility with C code.
760+ /// This means that the layout of a struct can change when it is used as a field in a larger
761+ /// struct. That is fundamentally incompatible with Rust: in Rust, you can always take a
762+ /// reference or pointer to a field and then use that pointer without knowing the larger struct
763+ /// it points inside. For packed structs, you have to worry about alignment, but the distance
764+ /// between the fields of the inner struct always remains the same. Not so on AIX, making this
765+ /// platform fundamentally incompatible with Rust.
763766 ///
764767 /// ### Example
765768 ///
766769 /// ```rust,ignore (fails on non-powerpc64-ibm-aix)
767770 /// #[repr(C)]
768771 /// pub struct Floats {
769772 /// a: f64,
773+ /// s: SecondFloat,
774+ /// }
775+ ///
776+ /// #[repr(C)]
777+ /// pub struct SecondFloat {
770778 /// b: u8,
771779 /// c: f64,
772780 /// }
@@ -776,24 +784,25 @@ declare_lint! {
776784 ///
777785 /// ```text
778786 /// warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
779- /// --> <source>:5 :3
787+ /// --> <source>:4 :3
780788 /// |
781- /// 5 | c: f64 ,
782- /// | ^^^^^^
789+ /// 4 | s: SecondFloat ,
790+ /// | ^^^^^^^^^^^^^^
783791 /// |
784792 /// = note: `#[warn(uses_power_alignment)]` on by default
785793 /// ```
786794 ///
787795 /// ### Explanation
788796 ///
789- /// The power alignment rule specifies that the above struct has the
790- /// following alignment:
791- /// - offset_of!(Floats, a ) == 0
792- /// - offset_of!(Floats , b) == 8
793- /// - offset_of!(Floats , c) == 12
797+ /// The power alignment rule specifies that the above struct has the following layout:
798+ /// - offset_of!(Floats, s.b) == 8
799+ /// - offset_of!(Floats, s.c ) == 12
800+ /// - offset_of!(SecondFloat , b) == 0
801+ /// - offset_of!(SecondFloat , c) == 8
794802 ///
795- /// However, Rust currently aligns `c` at `offset_of!(Floats, c) == 16`.
796- /// Using offset 12 would be unsound since `f64` generally must be 8-aligned on this target.
803+ /// The distance between `b` and `c` changes when `SecondFloat` is used as a field in a struct
804+ /// whose first field has a floating-point type. However, in Rust, the `b` and `c` fields must
805+ /// always have the same distance (in this case, they will be 8 bytes apart).
797806 /// Thus, a warning is produced for the above struct.
798807 USES_POWER_ALIGNMENT ,
799808 Warn ,
@@ -1629,9 +1638,6 @@ impl ImproperCTypesDefinitions {
16291638 // - the first field of the struct is an aggregate whose
16301639 // recursively first field is a floating-point type greater than
16311640 // 4 bytes.
1632- if cx. tcx . sess . target . os != "aix" {
1633- return false ;
1634- }
16351641 if ty. is_floating_point ( ) && ty. primitive_size ( cx. tcx ) . bytes ( ) > 4 {
16361642 return true ;
16371643 } else if let Adt ( adt_def, _) = ty. kind ( )
@@ -1668,15 +1674,11 @@ impl ImproperCTypesDefinitions {
16681674 // power alignment rule, as fields after the first are likely
16691675 // to be the fields that are misaligned.
16701676 if index != 0 {
1671- let first_field_def = struct_variant_data. fields ( ) [ index] ;
1672- let def_id = first_field_def . def_id ;
1677+ let field_def = struct_variant_data. fields ( ) [ index] ;
1678+ let def_id = field_def . def_id ;
16731679 let ty = cx. tcx . type_of ( def_id) . instantiate_identity ( ) ;
16741680 if self . check_arg_for_power_alignment ( cx, ty) {
1675- cx. emit_span_lint (
1676- USES_POWER_ALIGNMENT ,
1677- first_field_def. span ,
1678- UsesPowerAlignment ,
1679- ) ;
1681+ cx. emit_span_lint ( USES_POWER_ALIGNMENT , field_def. span , UsesPowerAlignment ) ;
16801682 }
16811683 }
16821684 }
0 commit comments