Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a4c0bf5
switch to v0 mangling by default on stable
davidtwco Feb 2, 2026
438d886
Lock stable_crate_ids once in create_crate_num
zetanumbers Apr 14, 2026
8591f0f
Tweak irrefutable let else warning output, add new suggestion
WeiTheShinobi Mar 24, 2026
3c362ec
Update documentation for `wasm32-wali-linux-musl` after integrating n…
arjunr2 Apr 24, 2026
c20757f
Add specific target diffs
arjunr2 Apr 24, 2026
da0fe8d
Overhaul the code for running an incremental test revision
Zalathar Apr 24, 2026
b7996bd
Existing code nits
BoxyUwU Feb 24, 2026
f5c39ef
Fix passing paths with space into dlltool
ChrisDenton Apr 28, 2026
2a8e588
Add `--print=backend-has-mnemonic` and `needs-asm-mnemonic` directive
fneddy Apr 23, 2026
4d4058b
Add regression test for hkl const closures
oli-obk Apr 28, 2026
b465c56
Handle hkl const closures
oli-obk Apr 28, 2026
f0b0950
Test that raw-dylib works with whitespace paths
ChrisDenton Apr 28, 2026
0eda44b
Delete the 12 year old fixme
mejrs Apr 28, 2026
62ee4cd
remove review queue triagebot mentions
davidtwco Apr 28, 2026
aef93ca
Document that CFI diverges from Rust wrt. ABI-compatibility rules
Darksonn Apr 28, 2026
c071091
Rollup merge of #151994 - davidtwco:v0-mangling-on-stable, r=wesleywiser
JonathanBrouwer Apr 28, 2026
19aacea
Rollup merge of #154325 - WeiTheShinobi:tweak-let-else-output, r=davi…
JonathanBrouwer Apr 28, 2026
f8e9d8e
Rollup merge of #155899 - ChrisDenton:dlltool, r=mati865
JonathanBrouwer Apr 28, 2026
9857def
Rollup merge of #155273 - zetanumbers:create_crate_num_lock, r=jdonsz…
JonathanBrouwer Apr 28, 2026
79bde2b
Rollup merge of #155361 - Darksonn:abi-cfi, r=RalfJung
JonathanBrouwer Apr 28, 2026
1d8b3c7
Rollup merge of #155692 - fneddy:fix_naked-dead-code-elimination, r=f…
JonathanBrouwer Apr 28, 2026
a4a5e8a
Rollup merge of #155747 - arjunr2:main, r=davidtwco
JonathanBrouwer Apr 28, 2026
efce51f
Rollup merge of #155768 - Zalathar:incremental, r=jieyouxu
JonathanBrouwer Apr 28, 2026
2fa0e6c
Rollup merge of #155907 - oli-obk:push-nypowoyskzxp, r=Kivooeo
JonathanBrouwer Apr 28, 2026
7002c54
Rollup merge of #155910 - BoxyUwU:borrowck_cleanup_5, r=lcnr
JonathanBrouwer Apr 28, 2026
203ff0a
Rollup merge of #155913 - mejrs:delete_the_fixme, r=nia-e
JonathanBrouwer Apr 28, 2026
71ee7fc
Rollup merge of #155920 - davidtwco:triagebot-remove-review-queue, r=…
JonathanBrouwer Apr 28, 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
18 changes: 8 additions & 10 deletions compiler/rustc_borrowck/src/handle_placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@ pub(crate) struct LoweredConstraints<'tcx> {
pub(crate) placeholder_indices: PlaceholderIndices<'tcx>,
}

impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
pub(crate) fn init(definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>) -> Self {
Self { scc_to_annotation: IndexVec::new(), definitions }
}
}

/// A Visitor for SCC annotation construction.
pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> {
pub(crate) scc_to_annotation: IndexVec<ConstraintSccIndex, A>,
definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>,
}

impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
pub(crate) fn init(definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>) -> Self {
Self { scc_to_annotation: IndexVec::new(), definitions }
}
}

impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
fn new(&self, element: RegionVid) -> RegionTracker {
RegionTracker::new(element, &self.definitions[element])
Expand Down Expand Up @@ -118,7 +118,7 @@ impl RegionTracker {
}

/// The largest universe this SCC can name. It's the smallest
/// largest nameable universe of any reachable region, or
/// max-nameable-universe of any reachable region, or
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
self.max_nameable_universe.0
Expand Down Expand Up @@ -208,7 +208,7 @@ pub(super) fn region_definitions<'tcx>(
/// graph such that there is a series of constraints
/// A: B: C: ... : X where
/// A contains a placeholder whose universe cannot be named by X,
/// add a constraint that A: 'static. This is a safe upper bound
/// add a constraint that X: 'static. This is a safe upper bound
/// in the face of borrow checker/trait solver limitations that will
/// eventually go away.
///
Expand Down Expand Up @@ -327,8 +327,6 @@ pub(crate) fn rewrite_placeholder_outlives<'tcx>(

for scc in sccs.all_sccs() {
// No point in adding 'static: 'static!
// This micro-optimisation makes somewhat sense
// because static outlives *everything*.
if scc == sccs.scc(fr_static) {
continue;
}
Expand Down
31 changes: 18 additions & 13 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,43 +501,48 @@ impl<'tcx> RegionInferenceContext<'tcx> {

let mut errors_buffer = RegionErrors::new(infcx.tcx);

// If this is a closure, we can propagate unsatisfied
// `outlives_requirements` to our creator, so create a vector
// to store those. Otherwise, we'll pass in `None` to the
// functions below, which will trigger them to report errors
// eagerly.
let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
// If this is a nested body, we propagate unsatisfied
// outlives constraints to the parent body instead of
// eagerly erroing.
let mut propagated_outlives_requirements =
infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);

self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer);
self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer);

debug!(?errors_buffer);
debug!(?outlives_requirements);
debug!(?propagated_outlives_requirements);

// In Polonius mode, the errors about missing universal region relations are in the output
// and need to be emitted or propagated. Otherwise, we need to check whether the
// constraints were too strong, and if so, emit or propagate those errors.
if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
self.check_polonius_subset_errors(
outlives_requirements.as_mut(),
propagated_outlives_requirements.as_mut(),
&mut errors_buffer,
polonius_output
.as_ref()
.expect("Polonius output is unavailable despite `-Z polonius`"),
);
} else {
self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer);
self.check_universal_regions(
propagated_outlives_requirements.as_mut(),
&mut errors_buffer,
);
}

debug!(?errors_buffer);

let outlives_requirements = outlives_requirements.unwrap_or_default();
let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default();

if outlives_requirements.is_empty() {
if propagated_outlives_requirements.is_empty() {
(None, errors_buffer)
} else {
let num_external_vids = self.universal_regions().num_global_and_external_regions();
(
Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }),
Some(ClosureRegionRequirements {
num_external_vids,
outlives_requirements: propagated_outlives_requirements,
}),
errors_buffer,
)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,7 @@ unsafe extern "C" {
pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);

pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
pub(crate) fn LLVMRustTargetHasMnemonic(T: &TargetMachine, s: *const c_char) -> bool;

pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString);
pub(crate) fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t;
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@ pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) {
match req.kind {
PrintKind::TargetCPUs => print_target_cpus(sess, tm.raw(), out),
PrintKind::TargetFeatures => print_target_features(sess, tm.raw(), out),
PrintKind::BackendHasMnemonic => {
let mnemonic = req.arg.as_deref().expect("BackendHasMnemonic requires arg");
print_target_has_mnemonic(tm.raw(), mnemonic, out)
}
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
}
}
Expand Down Expand Up @@ -738,3 +742,10 @@ pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> {
let name = sess.opts.unstable_opts.tune_cpu.as_ref()?;
Some(handle_native(name))
}

fn print_target_has_mnemonic(tm: &llvm::TargetMachine, mnemonic: &str, out: &mut String) {
use std::fmt::Write;
let cstr = SmallCStr::new(mnemonic);
let has_mnemonic = unsafe { llvm::LLVMRustTargetHasMnemonic(tm, cstr.as_ptr()) };
writeln!(out, "{}", has_mnemonic).unwrap();
}
13 changes: 6 additions & 7 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,10 @@ fn create_mingw_dll_import_lib(
// able to control the *exact* spelling of each of the symbols that are being imported:
// hence we don't want `dlltool` adding leading underscores automatically.
let dlltool = find_binutils_dlltool(sess);
let temp_prefix = {
let mut path = PathBuf::from(&output_path);
path.pop();
path.push(lib_name);
path
};
// temp_prefix doesn't handle paths with spaces so
// use a relative path and set the current working directory
let cwd = output_path.parent().unwrap_or(output_path);
let temp_prefix = lib_name;
// dlltool target architecture args from:
// https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
let (dlltool_target_arch, dlltool_target_bitness) = match &sess.target.arch {
Expand All @@ -246,7 +244,8 @@ fn create_mingw_dll_import_lib(
.arg(dlltool_target_bitness)
.arg("--no-leading-underscore")
.arg("--temp-prefix")
.arg(temp_prefix);
.arg(temp_prefix)
.current_dir(cwd);

match dlltool_cmd.output() {
Err(e) => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/graph/scc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ mod tests;
/// the max/min element of the SCC, or all of the above.
///
/// Concretely, the both merge operations must commute, e.g. where `merge`
/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)`
/// is `update_scc` and `update_reachable`: `a.merge(b) == b.merge(a)`
///
/// In general, what you want is probably always min/max according
/// to some ordering, potentially with side constraints (min x such
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,9 @@ fn print_crate_info(
let calling_conventions = rustc_abi::all_names();
println_info!("{}", calling_conventions.join("\n"));
}
BackendHasMnemonic => {
codegen_backend.print(req, &mut crate_info, sess);
}
BackendHasZstd => {
let has_zstd: bool = codegen_backend.has_zstd();
println_info!("{has_zstd}");
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/IR/Verifier.h"
#include "llvm/IRPrinter/IRPrintingPasses.h"
#include "llvm/LTO/LTO.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/ObjectFile.h"
Expand Down Expand Up @@ -94,6 +95,25 @@ extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
return MCInfo->checkFeatures(std::string("+") + Feature);
}

/// Check whether the target has a specific assembly mnemonic like `ret` or
/// `nop`.
/// This should be fast enough but if its not we have to look into another
/// method of checking.
extern "C" bool LLVMRustTargetHasMnemonic(LLVMTargetMachineRef TM,
const char *Mnemonic) {
TargetMachine *Target = unwrap(TM);
const MCInstrInfo *MII = Target->getMCInstrInfo();
StringRef MnemonicRef(Mnemonic);

for (unsigned i = 0; i < MII->getNumOpcodes(); i++) {
StringRef Name = MII->getName(i);
if (Name.equals_insensitive(MnemonicRef)) {
return true;
}
}
return false;
}

enum class LLVMRustCodeModel {
Tiny,
Small,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1416,12 +1416,12 @@ impl<'tcx> TyCtxt<'tcx> {
self,
stable_crate_id: StableCrateId,
) -> Result<TyCtxtFeed<'tcx, CrateNum>, CrateNum> {
if let Some(&existing) = self.untracked().stable_crate_ids.read().get(&stable_crate_id) {
let mut lock = self.untracked().stable_crate_ids.write();
if let Some(&existing) = lock.get(&stable_crate_id) {
return Err(existing);
}

let num = CrateNum::new(self.untracked().stable_crate_ids.read().len());
self.untracked().stable_crate_ids.write().insert(stable_crate_id, num);
let num = CrateNum::new(lock.len());
lock.insert(stable_crate_id, num);
Ok(TyCtxtFeed { key: num, tcx: self })
}

Expand Down
32 changes: 17 additions & 15 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -924,22 +924,24 @@ pub(crate) struct IrrefutableLetPatternsIfLetGuard {
}

#[derive(Diagnostic)]
#[diag(
"irrefutable `let...else` {$count ->
[one] pattern
*[other] patterns
}"
)]
#[note(
"{$count ->
[one] this pattern always matches, so the else clause is unreachable
*[other] these patterns always match, so the else clause is unreachable
}"
)]
#[diag("unreachable `else` clause")]
#[note("this pattern always matches, so the else clause is unreachable")]
pub(crate) struct IrrefutableLetPatternsLetElse {
pub(crate) count: usize,
#[help("remove this `else` block")]
pub(crate) else_span: Option<Span>,
#[subdiagnostic]
pub(crate) be_replaced: Option<LetElseReplacementSuggestion>,
}

#[derive(Subdiagnostic, Debug)]
#[suggestion(
"consider using `let {$lhs} = {$rhs}` to match on a specific variant",
code = "let {lhs} = {rhs}",
applicability = "machine-applicable"
)]
pub(crate) struct LetElseReplacementSuggestion {
#[primary_span]
pub(crate) span: Span,
pub(crate) lhs: String,
pub(crate) rhs: String,
}

#[derive(Diagnostic)]
Expand Down
71 changes: 64 additions & 7 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return };
// Lint only single irrefutable let binding.
if let [Some((_, Irrefutable))] = chain_refutabilities[..] {
self.lint_single_let(ex.span, None);
self.lint_single_let(ex.span, None, None);
}
return;
}
Expand Down Expand Up @@ -438,7 +438,45 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
if let LetSource::PlainLet = self.let_source {
self.check_binding_is_irrefutable(pat, "local binding", scrut, Some(span));
} else if let Ok(Irrefutable) = self.is_let_irrefutable(pat, scrut) {
self.lint_single_let(span, else_span);
if span.from_expansion() {
self.lint_single_let(span, None, None);
return;
}
let let_else_span = self.check_irrefutable_option_some(pat, scrut, span);

let sm = self.tcx.sess.source_map();
let next_token_start = sm.span_extend_while_whitespace(span.clone()).hi();
let line_span = sm.span_extend_to_line(span.clone()).with_lo(next_token_start);
let else_keyword_span = sm.span_until_whitespace(line_span);
self.lint_single_let(span, Some(else_keyword_span), let_else_span);
}
}

/// Check case `let x = Some(y);`, user likely intended to destructure `Option`
fn check_irrefutable_option_some(
&self,
pat: &'p Pat<'tcx>,
initializer: Option<&Expr<'tcx>>,
span: Span,
) -> Option<LetElseReplacementSuggestion> {
if let sm = self.tcx.sess.source_map()
&& let Some(initializer) = initializer
&& let Some(s_ty) = initializer.ty.ty_adt_def()
&& self.tcx.is_diagnostic_item(rustc_span::sym::Option, s_ty.did())
&& let ExprKind::Scope { value, .. } = initializer.kind
&& let initializer_expr = &self.thir[value]
&& let ExprKind::Adt(box AdtExpr { fields, .. }) = &initializer_expr.kind
&& let Some(field) = fields.first()
&& let inner = &self.thir[field.expr]
&& let Some(inner_ty) = inner.ty.ty_adt_def()
&& self.tcx.is_diagnostic_item(rustc_span::sym::Option, inner_ty.did())
&& let Ok(rhs) = sm.span_to_snippet(inner.span)
&& let Ok(lhs) = sm.span_to_snippet(pat.span)
{
let lhs = format!("Some({})", lhs);
Some(LetElseReplacementSuggestion { span, lhs, rhs })
} else {
None
}
}

Expand Down Expand Up @@ -559,14 +597,20 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
}

#[instrument(level = "trace", skip(self))]
fn lint_single_let(&mut self, let_span: Span, else_span: Option<Span>) {
fn lint_single_let(
&mut self,
let_span: Span,
else_keyword_span: Option<Span>,
let_else_span: Option<LetElseReplacementSuggestion>,
) {
report_irrefutable_let_patterns(
self.tcx,
self.hir_source,
self.let_source,
1,
let_span,
else_span,
else_keyword_span,
let_else_span,
);
}

Expand Down Expand Up @@ -862,7 +906,8 @@ fn report_irrefutable_let_patterns(
source: LetSource,
count: usize,
span: Span,
else_span: Option<Span>,
else_keyword_span: Option<Span>,
let_else_span: Option<LetElseReplacementSuggestion>,
) {
macro_rules! emit_diag {
($lint:tt) => {{
Expand All @@ -875,11 +920,23 @@ fn report_irrefutable_let_patterns(
LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet),
LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
LetSource::LetElse => {
let spans = match else_keyword_span {
Some(else_keyword_span) => {
let mut spans = MultiSpan::from_span(else_keyword_span);
spans.push_span_label(
span,
msg!("assigning to binding pattern will always succeed"),
);
spans
}
None => span.into(),
};

tcx.emit_node_span_lint(
IRREFUTABLE_LET_PATTERNS,
id,
span,
IrrefutableLetPatternsLetElse { count, else_span },
spans,
IrrefutableLetPatternsLetElse { be_replaced: let_else_span },
);
}
LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet),
Expand Down
Loading
Loading