Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0c8e360
RISC-V: Add zmmul target feature
TechnoPorg Sep 9, 2026
7a6e24a
Document interaction between "m" and "zmmul"
TechnoPorg Sep 10, 2026
d609aff
Tweak wording of comment in target_features.rs
TechnoPorg Sep 11, 2026
a33e6eb
Address review comments
TechnoPorg Sep 11, 2026
aadf13c
add `non_zst_field` helper
folkertdev Sep 13, 2026
ee524a2
fix `is_single_fp_element` for `s390x` and `x86`
folkertdev Aug 29, 2026
33871b9
abi/compatibility test: add simple float type tests
RalfJung Aug 29, 2026
5dd4631
rustc_{codegen_,}llvm: adapt to new ThreadModel API
durin42 Sep 15, 2026
3c283d4
Copy metadata workproduct when session dir rename fails
TheHighestBit Sep 6, 2026
26e7e77
Gate finalize_session_directory rename fallbacks to windows
TheHighestBit Sep 9, 2026
b4beb1e
Pass File to Fallback::lock
bjorn3 Sep 16, 2026
0143ce1
Have a separate copy of the flock code for rustdoc
bjorn3 Sep 16, 2026
435b07d
Remove wait argument from Lock::new
bjorn3 Sep 10, 2026
de50895
Introduce a global lock registry for the fcntl lock fallback
bjorn3 Sep 10, 2026
0bae8cf
Move metadata work product name into a constant
TheHighestBit Sep 15, 2026
4138d02
Remove redundant "add bound" help messages
nnethercote Sep 17, 2026
82ddf4c
Change "the following changes may resolve your lifetime errors" diagn…
nnethercote Sep 17, 2026
31fafe3
Clarify `Level::{Help,Note,FailureNote}` details
nnethercote Sep 17, 2026
6d008f3
libm: Avoid `debug_assert_eq!` if `feature = "compiler-builtins"`
tgross35 Sep 17, 2026
362d116
c-b: Export `fmaf16` now that we have an implementation
tgross35 Sep 10, 2026
2be177e
Use HashMap::entry
bjorn3 Sep 17, 2026
3c8dcac
Add regression tests for derive suggestions on generated enums
chenyukang Sep 10, 2026
4a1b4b0
Avoid derive edits on macro-generated types
chenyukang Sep 10, 2026
0db4e55
offload: add libLLVM rpath for libomptarget
sgasho Sep 16, 2026
9600948
Error on invalid uses of the `cfi_encoding` attribute.
mejrs Sep 17, 2026
85779af
Rollup merge of #161987 - folkertdev:single-fp-element, r=beetrees
JonathanBrouwer Sep 17, 2026
8297751
Rollup merge of #162366 - TheHighestBit:copy-on-finalize-error, r=bjorn3
JonathanBrouwer Sep 17, 2026
370012b
Rollup merge of #162552 - TechnoPorg:riscv-feature-zmmul, r=beetrees
JonathanBrouwer Sep 17, 2026
ed96d94
Rollup merge of #162602 - bjorn3:safer_fcntl_fallback, r=oli-obk
JonathanBrouwer Sep 17, 2026
d2aced1
Rollup merge of #162885 - nnethercote:rm-Level-Help, r=estebank
JonathanBrouwer Sep 17, 2026
32eaee3
Rollup merge of #162606 - tgross35:fmaf16-fallback, r=folkertdev
JonathanBrouwer Sep 17, 2026
c79bc2c
Rollup merge of #162817 - durin42:llvm-24-thread-model, r=nikic
JonathanBrouwer Sep 17, 2026
789d24b
Rollup merge of #162860 - sgasho:offload-remove-ldlibrarypath, r=ZuseZ4
JonathanBrouwer Sep 17, 2026
f29e823
Rollup merge of #162895 - chenyukang:yukang-fix-148207-generated-deri…
JonathanBrouwer Sep 17, 2026
95edc20
Rollup merge of #162899 - mejrs:cfi_encoding, r=JonathanBrouwer
JonathanBrouwer Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5056,6 +5056,7 @@ dependencies = [
"expect-test",
"indexmap",
"itertools",
"libc",
"minifier",
"proc-macro2",
"pulldown-cmark-escape",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_abi/src/callconv/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ impl Reg {
reg_ctor!(i64, Integer, 64);
reg_ctor!(i128, Integer, 128);

reg_ctor!(f16, Float, 16);
reg_ctor!(f32, Float, 32);
reg_ctor!(f64, Float, 64);
reg_ctor!(f128, Float, 128);
Expand Down
43 changes: 23 additions & 20 deletions compiler/rustc_abi/src/layout/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Ty::ty_and_layout_pointee_info_at(self, cx, offset)
}

pub fn is_single_fp_element<C>(self, cx: &C) -> bool
where
Ty: TyAbiInterface<'a, C>,
C: HasDataLayout,
{
match self.backend_repr {
BackendRepr::Scalar(scalar) => {
matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64))
}
BackendRepr::Memory { .. } => {
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
self.field(cx, 0).is_single_fp_element(cx)
} else {
false
}
}
_ => false,
}
}

pub fn is_single_vector_element<C>(self, cx: &C, expected_size: Size) -> bool
where
Ty: TyAbiInterface<'a, C>,
Expand Down Expand Up @@ -309,6 +289,29 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
found
}

/// Finds the one field that is not a ZST.
/// Returns `None` if there are multiple non-ZST fields or only ZST-fields.
///
/// Note that this function checks for ZSTs, not just 1-ZSTs.
pub fn non_zst_field_ignore_alignment<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>
where
Ty: TyAbiInterface<'a, C> + Copy,
{
let mut found = None;
for field_idx in 0..self.fields.count() {
let field = self.field(cx, field_idx);
if field.is_zst() {
continue;
}
if found.is_some() {
// More than one non-ZST field.
return None;
}
found = Some((FieldIdx::from_usize(field_idx), field));
}
found
}

/// If this type should match the ABI of the C `_Complex` type, returns the primitive that is
/// used for its components.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::prelude::*;
pub(crate) struct CfiEncodingParser;
impl SingleAttributeParser for CfiEncodingParser {
const PATH: &[Symbol] = &[sym::cfi_encoding];
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
Allow(Target::Struct),
Allow(Target::ForeignTy),
Allow(Target::Enum),
Expand Down
38 changes: 6 additions & 32 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,6 @@ pub(super) struct DescribePlaceOpt {

pub(super) struct IncludingTupleField(pub(super) bool);

pub(crate) enum BufferedDiag<'diag> {
Error(Diag<'diag>),
NonError(Diag<'diag, ()>),
}

impl<'diag> BufferedDiag<'diag> {
fn sort_span(&self) -> Span {
match self {
BufferedDiag::Error(diag) => diag.sort_span,
BufferedDiag::NonError(diag) => diag.sort_span,
}
}
}

#[derive(Default)]
pub(crate) struct BorrowckDiagnosticsBuffer<'diag, 'tcx> {
/// This field keeps track of move errors that are to be reported for given move indices.
Expand All @@ -108,16 +94,13 @@ pub(crate) struct BorrowckDiagnosticsBuffer<'diag, 'tcx> {

buffered_mut_errors: FxIndexMap<Span, (Diag<'diag>, usize)>,

/// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
buffered_diags: Vec<BufferedDiag<'diag>>,
/// Buffer of diagnostics to be reported.
buffered_diags: Vec<Diag<'diag>>,
}

impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> {
pub(crate) fn buffer_non_error(&mut self, diag: Diag<'diag, ()>) {
self.buffered_diags.push(BufferedDiag::NonError(diag));
}
pub(crate) fn buffer_error(&mut self, diag: Diag<'diag>) {
self.buffered_diags.push(BufferedDiag::Error(diag));
self.buffered_diags.push(diag);
}

pub(crate) fn emit_errors(&mut self) {
Expand All @@ -134,14 +117,9 @@ impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> {
}

if !self.buffered_diags.is_empty() {
self.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
for buffered_diag in self.buffered_diags.drain(..) {
match buffered_diag {
BufferedDiag::Error(diag) => {
diag.emit();
}
BufferedDiag::NonError(diag) => diag.emit(),
}
self.buffered_diags.sort_by_key(|diag| diag.sort_span);
for diag in self.buffered_diags.drain(..) {
diag.emit();
}
}
}
Expand All @@ -152,10 +130,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
self.diags_buffer.buffer_error(diag.with_dcx(self.dcx()));
}

pub(crate) fn buffer_non_error(&mut self, diag: Diag<'_, ()>) {
self.diags_buffer.buffer_non_error(diag.with_dcx(self.dcx()));
}

pub(crate) fn buffer_move_error(
&mut self,
move_out_indices: Vec<MoveOutIndex>,
Expand Down
79 changes: 26 additions & 53 deletions compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ use crate::MirBorrowckCtxt;

/// The different things we could suggest.
enum SuggestedConstraint {
/// Outlives(a, [b, c, d, ...]) => 'a: 'b + 'c + 'd + ...
Outlives(RegionName, SmallVec<[RegionName; 2]>),

/// 'a = 'b
Equal(RegionName, RegionName),

Expand Down Expand Up @@ -106,11 +103,10 @@ impl OutlivesSuggestionBuilder {
continue;
}

// There are three types of suggestions we can make:
// 1) Suggest a bound: 'a: 'b
// 2) Suggest replacing 'a with 'static. If any of `outlived` is `'static`, then we
// There are two types of suggestions we can make:
// 1) Suggest replacing 'a with 'static. If any of `outlived` is `'static`, then we
// should just replace 'a with 'static.
// 3) Suggest unifying 'a with 'b if we have both 'a: 'b and 'b: 'a
// 2) Suggest unifying 'a with 'b if we have both 'a: 'b and 'b: 'a

if outlived
.iter()
Expand All @@ -121,7 +117,7 @@ impl OutlivesSuggestionBuilder {
// We want to isolate out all lifetimes that should be unified and print out
// separate messages for them.

let (unified, other): (Vec<_>, Vec<_>) = outlived.into_iter().partition(
let unified = outlived.into_iter().filter(
// Do we have both 'fr: 'r and 'r: 'fr?
|(r, _)| {
self.constraints_to_add
Expand All @@ -130,17 +126,12 @@ impl OutlivesSuggestionBuilder {
},
);

for (r, bound) in unified.into_iter() {
for (r, bound) in unified {
if !unified_already.contains(fr) {
suggested.push(SuggestedConstraint::Equal(fr_name, bound));
unified_already.insert(r);
}
}

if !other.is_empty() {
let other = other.iter().map(|(_, rname)| *rname).collect::<SmallVec<_>>();
suggested.push(SuggestedConstraint::Outlives(fr_name, other))
}
}
}

Expand Down Expand Up @@ -202,54 +193,36 @@ impl OutlivesSuggestionBuilder {
return;
}

// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
// list of diagnostics.
let mut diag = if let [constraint] = suggested.as_slice() {
mbcx.dcx().struct_help(match constraint {
SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
format!("add bound `{a}: {}`", bs.join(" + "))
}

// Emit an error with a list of one or more help suggestions. This is a weird error because
// it's just there to provide somewhere to put the help suggestions that describe how to
// fix the one or more borrow errors already reported within the item.
let tcx = mbcx.infcx.tcx;
let def_id = mbcx.mir_def_id();
let span = tcx.def_ident_span(def_id).unwrap_or_else(|| tcx.def_span(def_id));
let mut diag = tcx
.dcx()
.struct_err("one or more lifetime errors were found in this item")
.with_span(span);

// Add suggestions.
for constraint in suggested {
match constraint {
SuggestedConstraint::Equal(a, b) => {
format!("`{a}` and `{b}` must be the same: replace one with the other")
diag.help(format!(
"`{a}` and `{b}` must be the same: replace one with the other",
));
}
SuggestedConstraint::Static(a) => format!("replace `{a}` with `'static`"),
})
} else {
// Create a new diagnostic.
let mut diag = mbcx
.infcx
.tcx
.dcx()
.struct_help("the following changes may resolve your lifetime errors");

// Add suggestions.
for constraint in suggested {
match constraint {
SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
diag.help(format!("add bound `{a}: {}`", bs.join(" + ")));
}
SuggestedConstraint::Equal(a, b) => {
diag.help(format!(
"`{a}` and `{b}` must be the same: replace one with the other",
));
}
SuggestedConstraint::Static(a) => {
diag.help(format!("replace `{a}` with `'static`"));
}
SuggestedConstraint::Static(a) => {
diag.help(format!("replace `{a}` with `'static`"));
}
}

diag
};
}

// We want this message to appear after other messages on the mir def.
let mir_span = mbcx.body.span;
diag.sort_span = mir_span.shrink_to_hi();

// Buffer the diagnostic
mbcx.buffer_non_error(diag);
mbcx.buffer_error(diag);
}
}
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,15 @@ pub(crate) unsafe fn create_module<'ll>(
);
}

if llvm_version >= (24, 0, 0) && sess.target.singlethread(&sess.internal_target_features) {
llvm::add_module_flag_str(
llmod,
llvm::ModuleFlagMergeBehavior::Error,
"thread-model",
"single",
);
}

// Add module flags specified via -Z llvm_module_flag
for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag {
let merge_behavior = match merge_behavior.as_str() {
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_codegen_llvm/src/va_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,19 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
let padded_size = 8;
let padding = padded_size - unpadded_size;

let gpr_type = indirect || !layout.is_single_fp_element(bx.cx);
// NOTE: if we ever allow aggregate types, this should handle structs with a single fp element.
let is_single_fp_element = |layout: TyAndLayout<'_>| -> bool {
match layout.layout.backend_repr() {
BackendRepr::Scalar(scalar) => match scalar.primitive() {
Primitive::Float(Float::F16 | Float::F32 | Float::F64) => true,
Primitive::Float(Float::F128) => false,
Primitive::Int(_, _) | Primitive::Pointer(_) => false,
},
_ => false,
}
};

let gpr_type = indirect || !is_single_fp_element(layout);
let (max_regs, reg_count, reg_save_index, reg_padding) =
if gpr_type { (5, gpr, 2, padding) } else { (4, fpr, 16, 0) };

Expand Down
13 changes: 6 additions & 7 deletions compiler/rustc_data_structures/src/flock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub enum Lock {
}

impl Lock {
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
pub fn try_lock(p: &Path, create: bool, exclusive: bool) -> io::Result<Lock> {
let mut open_options = OpenOptions::new();
open_options.read(true).write(true).create(create);
#[cfg(unix)]
Expand All @@ -32,17 +32,16 @@ impl Lock {

let file = open_options.open(p)?;

let res = match (wait, exclusive) {
(true, true) => file.lock(),
(true, false) => file.lock_shared(),
(false, true) => file.try_lock().map_err(io::Error::from),
(false, false) => file.try_lock_shared().map_err(io::Error::from),
let res = if exclusive {
file.try_lock().map_err(io::Error::from)
} else {
file.try_lock_shared().map_err(io::Error::from)
};

match res {
Ok(()) => Ok(Lock::FdLocked { _file: file }),
Err(err) if matches!(err.kind(), io::ErrorKind::Unsupported) => {
Ok(Lock::Fallback(fallback::Lock::new(p, wait, create, exclusive)?))
Ok(Lock::Fallback(fallback::Lock::try_lock(p, file, exclusive)?))
}
Err(err) => Err(err),
}
Expand Down
Loading
Loading