@@ -755,18 +755,26 @@ declare_lint! {
755
755
/// recursively first field (as in "at offset 0") modify the layout of
756
756
/// *subsequent* fields of the associated structs to use an alignment value
757
757
/// where the floating-point type is aligned on a 4-byte boundary.
758
+ /// This affects nested structs as well.
758
759
///
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.
763
766
///
764
767
/// ### Example
765
768
///
766
769
/// ```rust,ignore (fails on non-powerpc64-ibm-aix)
767
770
/// #[repr(C)]
768
771
/// pub struct Floats {
769
772
/// a: f64,
773
+ /// s: SecondFloat,
774
+ /// }
775
+ ///
776
+ /// #[repr(C)]
777
+ /// pub struct SecondFloat {
770
778
/// b: u8,
771
779
/// c: f64,
772
780
/// }
@@ -776,24 +784,25 @@ declare_lint! {
776
784
///
777
785
/// ```text
778
786
/// 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
780
788
/// |
781
- /// 5 | c: f64 ,
782
- /// | ^^^^^^
789
+ /// 4 | s: SecondFloat ,
790
+ /// | ^^^^^^^^^^^^^^
783
791
/// |
784
792
/// = note: `#[warn(uses_power_alignment)]` on by default
785
793
/// ```
786
794
///
787
795
/// ### Explanation
788
796
///
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
794
802
///
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).
797
806
/// Thus, a warning is produced for the above struct.
798
807
USES_POWER_ALIGNMENT ,
799
808
Warn ,
@@ -1629,9 +1638,6 @@ impl ImproperCTypesDefinitions {
1629
1638
// - the first field of the struct is an aggregate whose
1630
1639
// recursively first field is a floating-point type greater than
1631
1640
// 4 bytes.
1632
- if cx. tcx . sess . target . os != "aix" {
1633
- return false ;
1634
- }
1635
1641
if ty. is_floating_point ( ) && ty. primitive_size ( cx. tcx ) . bytes ( ) > 4 {
1636
1642
return true ;
1637
1643
} else if let Adt ( adt_def, _) = ty. kind ( )
@@ -1668,15 +1674,11 @@ impl ImproperCTypesDefinitions {
1668
1674
// power alignment rule, as fields after the first are likely
1669
1675
// to be the fields that are misaligned.
1670
1676
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 ;
1673
1679
let ty = cx. tcx . type_of ( def_id) . instantiate_identity ( ) ;
1674
1680
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 ) ;
1680
1682
}
1681
1683
}
1682
1684
}
0 commit comments