Skip to content

Commit

Permalink
Auto merge of rust-lang#135921 - matthiaskrgr:rollup-5mzn76m, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#134746 (Don't ICE in coerce when autoderef fails to structurally normalize non-WF type in new solver)
 - rust-lang#135552 ([AIX] Lint on structs that have a different alignment in AIX's C ABI)
 - rust-lang#135779 (CI: free disk on linux arm runner)
 - rust-lang#135790 (Update windows-gnu targets to set `DebuginfoKind::DWARF`)
 - rust-lang#135879 (fix outdated file path ref in llvm)
 - rust-lang#135883 (Remove erroneous `unsafe` in `BTreeSet::upper_bound_mut`)
 - rust-lang#135884 (remove implied end of slice)
 - rust-lang#135887 (improvements on `build_steps::test` implementation)
 - rust-lang#135898 (rustdoc-json-types: Finalize dyn compatibility renaming)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 23, 2025
2 parents fc0094f + 4b3d7ef commit 99768c8
Show file tree
Hide file tree
Showing 37 changed files with 669 additions and 94 deletions.
14 changes: 11 additions & 3 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// to the target type), since that should be the least
// confusing.
let Some(InferOk { value: ty, mut obligations }) = found else {
let err = first_error.expect("coerce_borrowed_pointer had no error");
debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
return Err(err);
if let Some(first_error) = first_error {
debug!("coerce_borrowed_pointer: failed with err = {:?}", first_error);
return Err(first_error);
} else {
// This may happen in the new trait solver since autoderef requires
// the pointee to be structurally normalizable, or else it'll just bail.
// So when we have a type like `&<not well formed>`, then we get no
// autoderef steps (even though there should be at least one). That means
// we get no type mismatches, since the loop above just exits early.
return Err(TypeError::Mismatch);
}
};

if ty == a && mt_a.mutbl.is_not() && autoderef.step_count() == 1 {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,8 @@ lint_unused_result = unused result of type `{$ty}`
lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result
lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
lint_variant_size_differences =
enum variant is more than three times larger ({$largest} bytes) than the next largest
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,10 @@ pub(crate) struct OverflowingLiteral<'a> {
pub lit: String,
}

#[derive(LintDiagnostic)]
#[diag(lint_uses_power_alignment)]
pub(crate) struct UsesPowerAlignment;

#[derive(LintDiagnostic)]
#[diag(lint_unused_comparisons)]
pub(crate) struct UnusedComparisons;
Expand Down
134 changes: 129 additions & 5 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::iter;
use std::ops::ControlFlow;

use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange};
use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagMessage;
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
use rustc_middle::ty::{
self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
self, Adt, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt,
};
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
use rustc_span::def_id::LocalDefId;
Expand All @@ -23,7 +24,7 @@ use crate::lints::{
AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, UsesPowerAlignment,
VariantSizeDifferencesDiag,
};
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
Expand Down Expand Up @@ -727,7 +728,60 @@ declare_lint! {
"proper use of libc types in foreign item definitions"
}

declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS]);
declare_lint! {
/// The `uses_power_alignment` lint detects specific `repr(C)`
/// aggregates on AIX.
/// In its platform C ABI, AIX uses the "power" (as in PowerPC) alignment
/// rule (detailed in https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=data-using-alignment-modes#alignment),
/// which can also be set for XLC by `#pragma align(power)` or
/// `-qalign=power`. Aggregates with a floating-point type as the
/// recursively first field (as in "at offset 0") modify the layout of
/// *subsequent* fields of the associated structs to use an alignment value
/// where the floating-point type is aligned on a 4-byte boundary.
///
/// The power alignment rule for structs needed for C compatibility is
/// unimplementable within `repr(C)` in the compiler without building in
/// handling of references to packed fields and infectious nested layouts,
/// so a warning is produced in these situations.
///
/// ### Example
///
/// ```rust,ignore (fails on non-powerpc64-ibm-aix)
/// #[repr(C)]
/// pub struct Floats {
/// a: f64,
/// b: u8,
/// c: f64,
/// }
/// ```
///
/// This will produce:
///
/// ```text
/// warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
/// --> <source>:5:3
/// |
/// 5 | c: f64,
/// | ^^^^^^
/// |
/// = note: `#[warn(uses_power_alignment)]` on by default
/// ```
///
/// ### Explanation
///
/// The power alignment rule specifies that the above struct has the
/// following alignment:
/// - offset_of!(Floats, a) == 0
/// - offset_of!(Floats, b) == 8
/// - offset_of!(Floats, c) == 12
/// However, rust currently aligns `c` at offset_of!(Floats, c) == 16.
/// Thus, a warning should be produced for the above struct in this case.
USES_POWER_ALIGNMENT,
Warn,
"Structs do not follow the power alignment rule under repr(C)"
}

declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS, USES_POWER_ALIGNMENT]);

#[derive(Clone, Copy)]
pub(crate) enum CItemKind {
Expand Down Expand Up @@ -1539,6 +1593,71 @@ impl ImproperCTypesDefinitions {
vis.check_type_for_ffi_and_report_errors(span, fn_ptr_ty, true, false);
}
}

fn check_arg_for_power_alignment<'tcx>(
&mut self,
cx: &LateContext<'tcx>,
ty: Ty<'tcx>,
) -> bool {
// Structs (under repr(C)) follow the power alignment rule if:
// - the first field of the struct is a floating-point type that
// is greater than 4-bytes, or
// - the first field of the struct is an aggregate whose
// recursively first field is a floating-point type greater than
// 4 bytes.
if cx.tcx.sess.target.os != "aix" {
return false;
}
if ty.is_floating_point() && ty.primitive_size(cx.tcx).bytes() > 4 {
return true;
} else if let Adt(adt_def, _) = ty.kind()
&& adt_def.is_struct()
{
let struct_variant = adt_def.variant(VariantIdx::ZERO);
// Within a nested struct, all fields are examined to correctly
// report if any fields after the nested struct within the
// original struct are misaligned.
for struct_field in &struct_variant.fields {
let field_ty = cx.tcx.type_of(struct_field.did).instantiate_identity();
if self.check_arg_for_power_alignment(cx, field_ty) {
return true;
}
}
}
return false;
}

fn check_struct_for_power_alignment<'tcx>(
&mut self,
cx: &LateContext<'tcx>,
item: &'tcx hir::Item<'tcx>,
) {
let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id());
if adt_def.repr().c()
&& !adt_def.repr().packed()
&& cx.tcx.sess.target.os == "aix"
&& !adt_def.all_fields().next().is_none()
{
let struct_variant_data = item.expect_struct().0;
for (index, ..) in struct_variant_data.fields().iter().enumerate() {
// Struct fields (after the first field) are checked for the
// power alignment rule, as fields after the first are likely
// to be the fields that are misaligned.
if index != 0 {
let first_field_def = struct_variant_data.fields()[index];
let def_id = first_field_def.def_id;
let ty = cx.tcx.type_of(def_id).instantiate_identity();
if self.check_arg_for_power_alignment(cx, ty) {
cx.emit_span_lint(
USES_POWER_ALIGNMENT,
first_field_def.span,
UsesPowerAlignment,
);
}
}
}
}
}
}

/// `ImproperCTypesDefinitions` checks items outside of foreign items (e.g. stuff that isn't in
Expand All @@ -1562,8 +1681,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
}
// See `check_fn`..
hir::ItemKind::Fn { .. } => {}
// Structs are checked based on if they follow the power alignment
// rule (under repr(C)).
hir::ItemKind::Struct(..) => {
self.check_struct_for_power_alignment(cx, item);
}
// See `check_field_def`..
hir::ItemKind::Union(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => {}
hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {}
// Doesn't define something that can contain a external type to be checked.
hir::ItemKind::Impl(..)
| hir::ItemKind::TraitAlias(..)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse_format/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ impl<'a> Parser<'a> {
}
}
}
&self.input[start..self.input.len()]
&self.input[start..]
}

/// Parses an `Argument` structure, or what's contained within braces inside the format string.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/spec/base/windows_gnu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ pub(crate) fn opts() -> TargetOptions {
emit_debug_gdb_scripts: false,
requires_uwtable: true,
eh_frame_header: false,
debuginfo_kind: DebuginfoKind::Dwarf,
// FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
// output DWO, despite using DWARF, doesn't use ELF..
debuginfo_kind: DebuginfoKind::Pdb,
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
..Default::default()
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/spec/base/windows_gnullvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ pub(crate) fn opts() -> TargetOptions {
has_thread_local: true,
crt_static_allows_dylibs: true,
crt_static_respected: true,
debuginfo_kind: DebuginfoKind::Dwarf,
// FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
// output DWO, despite using DWARF, doesn't use ELF..
debuginfo_kind: DebuginfoKind::Pdb,
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
..Default::default()
}
Expand Down
8 changes: 4 additions & 4 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,20 +1442,20 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
///
/// let mut set = BTreeSet::from([1, 2, 3, 4]);
///
/// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) };
/// let mut cursor = set.upper_bound_mut(Bound::Included(&3));
/// assert_eq!(cursor.peek_prev(), Some(&3));
/// assert_eq!(cursor.peek_next(), Some(&4));
///
/// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) };
/// let mut cursor = set.upper_bound_mut(Bound::Excluded(&3));
/// assert_eq!(cursor.peek_prev(), Some(&2));
/// assert_eq!(cursor.peek_next(), Some(&3));
///
/// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) };
/// let mut cursor = set.upper_bound_mut(Bound::Unbounded);
/// assert_eq!(cursor.peek_prev(), Some(&4));
/// assert_eq!(cursor.peek_next(), None);
/// ```
#[unstable(feature = "btree_cursors", issue = "107540")]
pub unsafe fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
pub fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
where
T: Borrow<Q> + Ord,
Q: Ord,
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/src/core/build_steps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,7 @@ impl Step for CrtBeginEnd {
.file(crtbegin_src)
.file(crtend_src);

// Those flags are defined in src/llvm-project/compiler-rt/lib/crt/CMakeLists.txt
// Those flags are defined in src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt
// Currently only consumer of those objects is musl, which use .init_array/.fini_array
// instead of .ctors/.dtors
cfg.flag("-std=c11")
Expand Down
Loading

0 comments on commit 99768c8

Please sign in to comment.