Skip to content

Commit 661de9f

Browse files
committed
use an example that more clearly shows the insanity of this target
1 parent 0ce0251 commit 661de9f

File tree

1 file changed

+26
-24
lines changed

1 file changed

+26
-24
lines changed

compiler/rustc_lint/src/types.rs

+26-24
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)