Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
8a7ec34
Stabilize `windows_process_extensions_main_thread_handle`
ChayimFriedman2 Jul 28, 2026
c317698
Make Receiver #[rustc_dyn_incompatible_trait]
Darksonn Sep 7, 2026
40bbaea
Fix test
Darksonn Sep 7, 2026
58c9d2f
core: Rewrite docs for try_as_dyn
jnkel Sep 14, 2026
324f136
Fix a bug in MatchBranchSimplification
saethlin Sep 14, 2026
6401a6e
libtest: do not early exit from test runners
RalfJung Sep 15, 2026
5fd598e
clean up libtest re-exports a bit
RalfJung Sep 15, 2026
f05d37a
extract hardcoded polonius MIR dump into HTML template
lqd Sep 4, 2026
6f49dfe
add loan reachability to the polonius mir dump
lqd Sep 15, 2026
5e715e0
make loan traces opt in
lqd Sep 15, 2026
2cd2f3d
improve visuals
lqd Sep 15, 2026
6b96623
core: Add examples for `debug_closure_helpers`
tgross35 Sep 15, 2026
9559b38
Stabilize trim_prefix_suffix
zachs18 Aug 5, 2026
076a758
enable asm tests for xtensa targets
RalfJung Sep 16, 2026
babc228
mgca: fix issue with mismatched array valtree/valtree tys
khyperia Sep 16, 2026
9dce1fc
reintroduce check for ConstParamTy in direct consts
khyperia Sep 16, 2026
fb554f2
Read alias liveness directly from item bounds
Dnreikronos Sep 16, 2026
94cc692
Stabilize CommandExt::show_window
nodamushi Sep 16, 2026
8265b6f
Use the entire type of the live variable to compute region variance
amandasystems Sep 16, 2026
0a1618e
coretests: Add more pattern tests.
pacak Aug 10, 2026
c8cb67c
tests: accept LLVM 24 optimization in this test
durin42 Aug 26, 2026
f20db0d
make `Complex::new` a `const fn`
folkertdev Sep 16, 2026
0e46d8f
add `Complex::conjugate` and `impl<T: Neg> Neg for Complex<T>`
folkertdev Sep 16, 2026
54e0102
add `impl<T: Default> Default for Complex<T>`
folkertdev Sep 16, 2026
99261fb
Add must_use lint to ExitCode
ChrisDenton Sep 15, 2026
d38f60b
Add support for `annotate_snippets::snippet::AnnotationKind::Visible`
estebank Sep 16, 2026
5981733
Use `span_context` in more places
estebank Sep 16, 2026
591e081
Use context span more
estebank Sep 16, 2026
79d24a0
Move operations out of `rustc_middle::query::job`
nnethercote Aug 20, 2026
a788afa
Simplify the macro for forwarding Decoder methods
Zalathar Sep 15, 2026
c095b61
Remove Deref/DerefMut from MetadataDecodeContext
Zalathar Sep 17, 2026
caedbd8
yeet alias new_from_def_id
khyperia Sep 17, 2026
c20275b
Typo on the Armv7-R platform docs page
jonathanpallant Sep 17, 2026
92b9d6c
Rollup merge of #161596 - pacak:more-pat-tests, r=nia-e
JonathanBrouwer Sep 17, 2026
8773e85
Rollup merge of #162411 - Darksonn:receiver-dyn-incompat, r=dingxiang…
JonathanBrouwer Sep 17, 2026
7ddb377
Rollup merge of #162760 - khyperia:yeet-new_from_def_id, r=BoxyUwU
JonathanBrouwer Sep 17, 2026
757cb99
Rollup merge of #162796 - RalfJung:libtest-no-early-exit, r=oli-obk
JonathanBrouwer Sep 17, 2026
7e15465
Rollup merge of #162844 - lqd:traceroute, r=jackh726
JonathanBrouwer Sep 17, 2026
15d7810
Rollup merge of #162876 - nnethercote:mv-ops-out-of-rustc_middle-quer…
JonathanBrouwer Sep 17, 2026
6134f46
Rollup merge of #160108 - ChayimFriedman2:stabilize-main-thread-windo…
JonathanBrouwer Sep 17, 2026
13225fe
Rollup merge of #160212 - Dnreikronos:traits/rigid_alias_liveness, r=…
JonathanBrouwer Sep 17, 2026
ce606c6
Rollup merge of #160544 - zachs18:stabilize-trim_prefix_suffix, r=cla…
JonathanBrouwer Sep 17, 2026
d025f9b
Rollup merge of #161305 - amandasystems:issue-160670, r=lqd,jackh726
JonathanBrouwer Sep 17, 2026
a9793c5
Rollup merge of #161838 - durin42:llvm-24-closure-inherit-target-feat…
JonathanBrouwer Sep 17, 2026
4259d00
Rollup merge of #162312 - jnkel:try_as_dyn-docs, r=oli-obk
JonathanBrouwer Sep 17, 2026
94a6233
Rollup merge of #162785 - saethlin:match_branch_simplification, r=oli…
JonathanBrouwer Sep 17, 2026
b47b950
Rollup merge of #162805 - ChrisDenton:exit-code-must-use, r=jhpratt
JonathanBrouwer Sep 17, 2026
35bc3a7
Rollup merge of #162825 - tgross35:debug-closure-examples, r=clarfonthey
JonathanBrouwer Sep 17, 2026
190a845
Rollup merge of #162841 - RalfJung:xtensa-asm, r=nnethercote
JonathanBrouwer Sep 17, 2026
004ecb2
Rollup merge of #162842 - khyperia:ConstParamTy-check, r=BoxyUwU
JonathanBrouwer Sep 17, 2026
065ca0f
Rollup merge of #162845 - khyperia:lowering-array-len-ty, r=BoxyUwU
JonathanBrouwer Sep 17, 2026
b6afcb5
Rollup merge of #162856 - nodamushi:stabilize-command-ext-show-window…
JonathanBrouwer Sep 17, 2026
4011b08
Rollup merge of #162865 - folkertdev:complex-conjugate, r=nia-e
JonathanBrouwer Sep 17, 2026
0dc3ef9
Rollup merge of #162874 - estebank:annotate-snippets-context, r=oli-obk
JonathanBrouwer Sep 17, 2026
8d19cc0
Rollup merge of #162881 - Zalathar:impl-decoder, r=nnethercote
JonathanBrouwer Sep 17, 2026
d775114
Rollup merge of #162888 - ferrocene:jp/fix-armv7r-typo, r=jieyouxu
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 @@ -4716,6 +4716,7 @@ name = "rustc_query_impl"
version = "0.0.0"
dependencies = [
"measureme",
"parking_lot",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,17 +1201,15 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
}
// Point at all the loops that are between this move and the parent item.
for span in loop_spans {
spans.push_span_label(sm.guess_head_span(span), "");
spans.push_span_context(sm.guess_head_span(span));
}

// note: verify that your loop breaking logic is correct
// --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
// |
// 28 | for foo in foos {
// | ---------------
// ...
// 33 | for bar in &bars {
// | ----------------
// ...
// 41 | continue;
// | ^^^^^^^^ this `continue` advances the loop at line 33
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
kind: hir::ImplItemKind::Fn(sig, _),
..
}) => {
err.span_label(ident.span, "");
err.span_context(ident.span);
err.span_label(
sig.decl.output.span(),
"change this to return `FnMut` instead of `Fn`",
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_borrowck/src/polonius/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use rustc_index::interval::SparseIntervalMatrix;
use rustc_middle::mir::{Body, Location};
use rustc_middle::ty::RegionVid;
use rustc_mir_dataflow::points::PointIndex;
use tracing::debug;

use crate::BorrowSet;
use crate::constraints::OutlivesConstraint;
Expand Down Expand Up @@ -253,6 +254,7 @@ fn compute_forward_successor(

// 2. Otherwise, gather the edges due to explicit region liveness, when applicable.
if !live_regions.contains(region, next_point) {
debug!(?region, ?next_point, "region isn't live at successor");
return None;
}

Expand All @@ -272,6 +274,8 @@ fn compute_forward_successor(
.flatten()
.unwrap_or(ConstraintDirection::Bidirectional);

debug!(?direction);

match direction {
ConstraintDirection::Backward => {
// Contravariant cases: loans flow in the inverse direction, but we're only interested
Expand Down Expand Up @@ -300,6 +304,7 @@ fn compute_backward_successor(
// Liveness flows into the regions live at the next point. So, in a backwards view, we'll link
// the region from the current point, if it's live there, to the previous point.
if !live_regions.contains(region, current_point) {
debug!(?region, ?current_point, "region isn't live at current point");
return None;
}

Expand Down
241 changes: 158 additions & 83 deletions compiler/rustc_borrowck/src/polonius/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ use rustc_session::config::MirIncludeSpans;

use crate::borrow_set::BorrowSet;
use crate::constraints::OutlivesConstraint;
use crate::dataflow::BorrowIndex;
use crate::polonius::{LocalizedConstraintGraphVisitor, LocalizedNode, PoloniusContext};
use crate::region_infer::values::LivenessValues;
use crate::type_check::Locations;
use crate::{BorrowckInferCtxt, ClosureRegionRequirements, RegionInferenceContext};

/// The polonius MIR dump template: a regular HTML file for easy editing, with special dummy
/// sections to be replaced by real contents.
const TEMPLATE: &str = include_str!("./dump/polonius-mir-dump.template.html");

/// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
pub(crate) fn dump_polonius_mir<'tcx>(
infcx: &BorrowckInferCtxt<'tcx>,
Expand All @@ -36,7 +41,7 @@ pub(crate) fn dump_polonius_mir<'tcx>(

// If we have a polonius graph to dump along the rest of the MIR and NLL info, we extract its
// constraints here.
let mut collector = LocalizedOutlivesConstraintCollector { constraints: Vec::new() };
let mut collector = MirDumpCollector::default();
if let Some(graph) = &polonius_context.graph {
graph.traverse(
body,
Expand Down Expand Up @@ -72,7 +77,7 @@ pub(crate) fn dump_polonius_mir<'tcx>(

let _ = try {
let mut file = dumper.create_dump_file("html", body)?;
emit_polonius_dump(&dumper, body, regioncx, borrow_set, &collector.constraints, &mut file)?;
emit_polonius_dump(&dumper, body, regioncx, borrow_set, &collector, &mut file)?;
};
}

Expand All @@ -84,12 +89,19 @@ struct LocalizedOutlivesConstraint {
to: PointIndex,
}

/// Visitor to record constraints encountered when traversing the localized constraint graph.
struct LocalizedOutlivesConstraintCollector {
/// Visitor to record constraints encountered when traversing the localized constraint graph, as
/// well as the reachability of each loan.
#[derive(Default)]
struct MirDumpCollector {
constraints: Vec<LocalizedOutlivesConstraint>,
reachability: FxIndexMap<BorrowIndex, Vec<LocalizedNode>>,
}

impl LocalizedConstraintGraphVisitor for LocalizedOutlivesConstraintCollector {
impl LocalizedConstraintGraphVisitor for MirDumpCollector {
fn on_node_traversed(&mut self, loan: BorrowIndex, node: LocalizedNode) {
self.reachability.entry(loan).or_default().push(node);
}

fn on_successor_discovered(&mut self, current_node: LocalizedNode, successor: LocalizedNode) {
self.constraints.push(LocalizedOutlivesConstraint {
source: current_node.region,
Expand All @@ -111,75 +123,77 @@ fn emit_polonius_dump<'tcx>(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
borrow_set: &BorrowSet<'tcx>,
localized_outlives_constraints: &[LocalizedOutlivesConstraint],
collector: &MirDumpCollector,
out: &mut dyn io::Write,
) -> io::Result<()> {
// Prepare the HTML dump file prologue.
writeln!(out, "<!DOCTYPE html>")?;
writeln!(out, "<html>")?;
writeln!(out, "<head><title>Polonius MIR dump</title></head>")?;
writeln!(out, "<body>")?;

// Section 1: the NLL + Polonius MIR.
writeln!(out, "<div>")?;
writeln!(out, "Raw MIR dump")?;
writeln!(out, "<pre><code>")?;
emit_html_mir(dumper, body, out)?;
writeln!(out, "</code></pre>")?;
writeln!(out, "</div>")?;

// Section 2: mermaid visualization of the polonius constraint graph.
writeln!(out, "<div>")?;
writeln!(out, "Polonius constraint graph")?;
writeln!(out, "<pre class='mermaid'>")?;
let edge_count = emit_mermaid_constraint_graph(
borrow_set,
regioncx.liveness_constraints(),
&localized_outlives_constraints,
out,
)?;
writeln!(out, "</pre>")?;
writeln!(out, "</div>")?;

// Section 3: mermaid visualization of the CFG.
writeln!(out, "<div>")?;
writeln!(out, "Control-flow graph")?;
writeln!(out, "<pre class='mermaid'>")?;
emit_mermaid_cfg(body, out)?;
writeln!(out, "</pre>")?;
writeln!(out, "</div>")?;

// Section 4: mermaid visualization of the NLL region graph.
writeln!(out, "<div>")?;
writeln!(out, "NLL regions")?;
writeln!(out, "<pre class='mermaid'>")?;
emit_mermaid_nll_regions(dumper.tcx(), regioncx, out)?;
writeln!(out, "</pre>")?;
writeln!(out, "</div>")?;

// Section 5: mermaid visualization of the NLL SCC graph.
writeln!(out, "<div>")?;
writeln!(out, "NLL SCCs")?;
writeln!(out, "<pre class='mermaid'>")?;
emit_mermaid_nll_sccs(dumper.tcx(), regioncx, out)?;
writeln!(out, "</pre>")?;
writeln!(out, "</div>")?;

// Finalize the dump with the HTML epilogue.
writeln!(
out,
"<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script>"
)?;
writeln!(out, "<script>")?;
writeln!(
out,
"mermaid.initialize({{ startOnLoad: false, maxEdges: {} }});",
edge_count.max(100),
)?;
writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?;
writeln!(out, "</script>")?;
writeln!(out, "</body>")?;
writeln!(out, "</html>")?;
let mut edge_count = 0;

// We replace the dummy $SECTION tokens from the HTML polonius dump template, and emit the
// result into the given writer.
for chunk in TEMPLATE.split("$SECTION") {
match chunk.strip_prefix("_") {
None => {
// We're at the beginning of the template: this is the prologue to emit as-is.
writeln!(out, "{}", chunk)?;
}
Some(section) => {
// This is the start of a prefixed section, we look for its identifier.
let dummy_section_end = section
.find("<")
.expect("the template section end boundary needs to be present");
let section_identifier = section[..dummy_section_end].trim();

// Emit the real section instead of the dummy token.
match section_identifier {
"MIR" => {
emit_html_mir(dumper, body, out)?;
}
"POLONIUS_CONSTRAINTS" => {
edge_count = emit_mermaid_constraint_graph(
borrow_set,
regioncx.liveness_constraints(),
&collector.constraints,
out,
)?;
}
"POLONIUS_REACHABILITY" => {
emit_loan_reachability(
borrow_set,
regioncx.liveness_constraints(),
&collector.reachability,
out,
)?;
}
"CFG" => {
emit_mermaid_cfg(body, out)?;
}
"NLL_CONSTRAINTS" => {
emit_mermaid_nll_regions(dumper.tcx(), regioncx, out)?;
}
"NLL_SCCS" => {
emit_mermaid_nll_sccs(dumper.tcx(), regioncx, out)?;
}
"INITIALIZATION" => {
writeln!(out, "<script>")?;
writeln!(
out,
"mermaid.initialize({{ startOnLoad: false, maxEdges: {} }});",
edge_count.max(100),
)?;
writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?;
writeln!(out, "</script>")?;
}

_ => {
unreachable!("unexpected dummy section identifier {:?}", section_identifier)
}
}

// And finally, emit the contents that followed the dummy token.
writeln!(out, "{}", &section[dummy_section_end..])?;
}
}
}

Ok(())
}
Expand Down Expand Up @@ -431,15 +445,9 @@ fn emit_mermaid_constraint_graph<'tcx>(
localized_outlives_constraints: &[LocalizedOutlivesConstraint],
out: &mut dyn io::Write,
) -> io::Result<usize> {
let location_name = |location: Location| {
// A MIR location looks like `bb5[2]`. As that is not a syntactically valid mermaid node id,
// transform it into `BB5_2`.
format!("BB{}_{}", location.block.index(), location.statement_index)
};
let region_name = |region: RegionVid| format!("'{}", region.index());
let node_name = |region: RegionVid, point: PointIndex| {
let node_label = |region: RegionVid, point: PointIndex| {
let location = liveness.location_from_point(point);
format!("{}_{}", region_name(region), location_name(location))
node_name(region, location)
};

// The mermaid chart type: a top-down flowchart, which supports subgraphs.
Expand Down Expand Up @@ -474,7 +482,7 @@ fn emit_mermaid_constraint_graph<'tcx>(
for (region, points) in points_per_region {
writeln!(out, " subgraph \"{}\"", region_name(region))?;
for point in points {
writeln!(out, " {}", node_name(region, point))?;
writeln!(out, " {}", node_label(region, point))?;
}
writeln!(out, " end\n")?;
}
Expand All @@ -485,8 +493,8 @@ fn emit_mermaid_constraint_graph<'tcx>(
writeln!(
out,
" {} --> {}",
node_name(constraint.source, constraint.from),
node_name(constraint.target, constraint.to),
node_label(constraint.source, constraint.from),
node_label(constraint.target, constraint.to),
)?;
}

Expand All @@ -495,3 +503,70 @@ fn emit_mermaid_constraint_graph<'tcx>(
let edge_count = borrow_set.len() + localized_outlives_constraints.len();
Ok(edge_count)
}

/// Emits the reachability of loans: a list of all nodes reached while traversing the polonius
/// constraint graph.
fn emit_loan_reachability(
borrow_set: &BorrowSet<'_>,
liveness: &LivenessValues,
reachability: &FxIndexMap<BorrowIndex, Vec<LocalizedNode>>,
out: &mut dyn io::Write,
) -> io::Result<()> {
for (loan, _) in borrow_set.iter_enumerated() {
let Some(reachability) = reachability.get(&loan) else {
continue;
};
let loan = format!("L{}", loan.index());

// The button to display the loan trace. The javascript event listener is hooked up in the
// template itself.
writeln!(
out,
"<div class='trace'><button data-loan='{loan}'>Trace for loan {loan}</button></div>"
)?;

// The actual trace contents, hidden by default.
writeln!(out, "<div id='trace-{loan}' class='trace hidden'>")?;
writeln!(out, "<div>Trace for loan {loan}</div>")?;
writeln!(out, "<ul>")?;
for (idx, node) in reachability.iter().enumerate() {
writeln!(out, "<li>")?;

let location = liveness.location_from_point(node.point);
let kind = if idx == 0 { "starts in" } else { "reaches" };
writeln!(
out,
"<code>{loan}</code> {kind} <code>{}</code>",
node_name(node.region, location),
)?;

// It's useful to know whether the region we're reaching is live at this point.
let node_liveness =
if liveness.is_live_at(node.region, location) { "live" } else { "not live" };
writeln!(
out,
"/ at <code>{:?}</code>: <code>'{}</code> is {}",
location,
node.region.index(),
node_liveness,
)?;
writeln!(out, "</li>")?;
}
writeln!(out, "</ul>")?;
writeln!(out, "</div>")?;
}

Ok(())
}

fn region_name(region: RegionVid) -> String {
format!("'{}", region.index())
}
/// A MIR location looks like `bb5[2]`. As that is not a syntactically valid mermaid node id,
/// transform it into `BB5_2`.
fn location_name(location: Location) -> String {
format!("BB{}_{}", location.block.index(), location.statement_index)
}
fn node_name(region: RegionVid, location: Location) -> String {
format!("{}_{}", region_name(region), location_name(location))
}
Loading
Loading