@@ -755,10 +755,10 @@ declare_lint! {
755
755
/// *subsequent* fields of the associated structs to use an alignment value
756
756
/// where the floating-point type is aligned on a 4-byte boundary.
757
757
///
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 .
762
762
///
763
763
/// ### Example
764
764
///
@@ -790,8 +790,10 @@ declare_lint! {
790
790
/// - offset_of!(Floats, a) == 0
791
791
/// - offset_of!(Floats, b) == 8
792
792
/// - 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.
795
797
USES_POWER_ALIGNMENT,
796
798
Warn,
797
799
"Structs do not follow the power alignment rule under repr(C)"
@@ -1655,15 +1657,13 @@ impl ImproperCTypesDefinitions {
1655
1657
cx: &LateContext<'tcx>,
1656
1658
ty: Ty<'tcx>,
1657
1659
) -> bool {
1660
+ assert!(cx.tcx.sess.target.os == "aix");
1658
1661
// Structs (under repr(C)) follow the power alignment rule if:
1659
1662
// - the first field of the struct is a floating-point type that
1660
1663
// is greater than 4-bytes, or
1661
1664
// - the first field of the struct is an aggregate whose
1662
1665
// recursively first field is a floating-point type greater than
1663
1666
// 4 bytes.
1664
- if cx.tcx.sess.target.os != "aix" {
1665
- return false;
1666
- }
1667
1667
if ty.is_floating_point() && ty.primitive_size(cx.tcx).bytes() > 4 {
1668
1668
return true;
1669
1669
} else if let Adt(adt_def, _) = ty.kind()
@@ -1701,21 +1701,14 @@ impl ImproperCTypesDefinitions {
1701
1701
&& !adt_def.all_fields().next().is_none()
1702
1702
{
1703
1703
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 ) {
1705
1705
// Struct fields (after the first field) are checked for the
1706
1706
// power alignment rule, as fields after the first are likely
1707
1707
// 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);
1719
1712
}
1720
1713
}
1721
1714
}
0 commit comments