about summary refs log tree commit diff
path: root/compiler/rustc_borrowck
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-08-15 14:38:17 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2025-09-01 09:19:03 +1000
commit5ce3797073ee5e6cc487b80effbc682533d9425c (patch)
tree06a143d06ef4deed8856880424c3ff824cdbf756 /compiler/rustc_borrowck
parent2d21c134054b6d337d4a1b81550a1ad10509b913 (diff)
downloadrust-5ce3797073ee5e6cc487b80effbc682533d9425c.tar.gz
rust-5ce3797073ee5e6cc487b80effbc682533d9425c.zip
Introduce `MirDumper` and `MirWriter`.
MIR dumping is a mess. There are lots of functions and entry points,
e.g. `dump_mir`, `dump_mir_with_options`, `dump_polonius_mir`,
`dump_mir_to_writer`. Also, it's crucial that `create_dump_file` is
never called without `dump_enabled` first being checked, but there is no
mechanism for ensuring this and it's hard to tell if it is satisfied on
all paths. (`dump_enabled` is checked twice on some paths, however!)

This commit introduces `MirWriter`, which controls the MIR writing, and
encapsulates the `extra_data` closure and `options`. Two existing
functions are now methods of this type. It sets reasonable defaults,
allowing the removal of many `|_, _| Ok(())` closures.

The commit also introduces `MirDumper`, which is layered on top of
`MirWriter`, and which manages the creation of the dump files,
encapsulating pass names, disambiguators, etc. Four existing functions
are now methods of this type.
- `MirDumper::new` will only succeed if dumps are enabled, and will
  return `None` otherwise, which makes it impossible to dump when you
  shouldn't.
- It also sets reasonable defaults for various things like
  disambiguators, which means you no longer need to specify them in many
  cases. When they do need to be specified, it's now done via setter
  methods.
- It avoids some repetition. E.g. `dump_nll_mir` previously specifed the
  pass name `"nll"` four times and the disambiguator `&0` three times;
  now it specifies them just once, to put them in the `MirDumper`.
- For Polonius, the `extra_data` closure can now be specified earlier,
  which avoids having to pass some arguments through some functions.
Diffstat (limited to 'compiler/rustc_borrowck')
-rw-r--r--compiler/rustc_borrowck/src/nll.rs35
-rw-r--r--compiler/rustc_borrowck/src/polonius/dump.rs87
2 files changed, 48 insertions, 74 deletions
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 021dba9c9a9..eb0f56bb869 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -8,8 +8,8 @@ use std::str::FromStr;
 use polonius_engine::{Algorithm, AllFacts, Output};
 use rustc_data_structures::frozen::Frozen;
 use rustc_index::IndexSlice;
-use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
-use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir};
+use rustc_middle::mir::pretty::PrettyPrintMirOptions;
+use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_mir_dataflow::move_paths::MoveData;
@@ -68,7 +68,9 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
     // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, body, promoted);
 
-    dump_mir(infcx.tcx, false, "renumber", &0, body, &|_, _| Ok(()));
+    if let Some(dumper) = MirDumper::new(infcx.tcx, "renumber", body) {
+        dumper.dump_mir(body);
+    }
 
     universal_regions
 }
@@ -175,9 +177,7 @@ pub(super) fn dump_nll_mir<'tcx>(
     borrow_set: &BorrowSet<'tcx>,
 ) {
     let tcx = infcx.tcx;
-    if !dump_enabled(tcx, "nll", body.source.def_id()) {
-        return;
-    }
+    let Some(dumper) = MirDumper::new(tcx, "nll", body) else { return };
 
     // We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in
     // #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example,
@@ -188,27 +188,24 @@ pub(super) fn dump_nll_mir<'tcx>(
             MirIncludeSpans::On | MirIncludeSpans::Nll
         ),
     };
-    dump_mir_with_options(
-        tcx,
-        false,
-        "nll",
-        &0,
-        body,
-        &|pass_where, out| {
-            emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out)
-        },
-        options,
-    );
+
+    let extra_data = &|pass_where, out: &mut dyn std::io::Write| {
+        emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out)
+    };
+
+    let dumper = dumper.set_extra_data(extra_data).set_options(options);
+
+    dumper.dump_mir(body);
 
     // Also dump the region constraint graph as a graphviz file.
     let _: io::Result<()> = try {
-        let mut file = create_dump_file(tcx, "regioncx.all.dot", false, "nll", &0, body)?;
+        let mut file = dumper.create_dump_file("regioncx.all.dot", body)?;
         regioncx.dump_graphviz_raw_constraints(tcx, &mut file)?;
     };
 
     // Also dump the region constraint SCC graph as a graphviz file.
     let _: io::Result<()> = try {
-        let mut file = create_dump_file(tcx, "regioncx.scc.dot", false, "nll", &0, body)?;
+        let mut file = dumper.create_dump_file("regioncx.scc.dot", body)?;
         regioncx.dump_graphviz_scc_constraints(tcx, &mut file)?;
     };
 }
diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs
index 173fb596976..62f9ae17347 100644
--- a/compiler/rustc_borrowck/src/polonius/dump.rs
+++ b/compiler/rustc_borrowck/src/polonius/dump.rs
@@ -2,9 +2,7 @@ use std::io;
 
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_index::IndexVec;
-use rustc_middle::mir::pretty::{
-    PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
-};
+use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions};
 use rustc_middle::mir::{Body, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::points::PointIndex;
@@ -33,22 +31,41 @@ pub(crate) fn dump_polonius_mir<'tcx>(
         return;
     }
 
-    if !dump_enabled(tcx, "polonius", body.source.def_id()) {
-        return;
-    }
+    let Some(dumper) = MirDumper::new(tcx, "polonius", body) else { return };
 
     let polonius_diagnostics =
         polonius_diagnostics.expect("missing diagnostics context with `-Zpolonius=next`");
 
+    let extra_data = &|pass_where, out: &mut dyn io::Write| {
+        emit_polonius_mir(
+            tcx,
+            regioncx,
+            closure_region_requirements,
+            borrow_set,
+            &polonius_diagnostics.localized_outlives_constraints,
+            pass_where,
+            out,
+        )
+    };
+    // We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
+    // mir-include-spans` on the CLI still has priority.
+    let options = PrettyPrintMirOptions {
+        include_extra_comments: matches!(
+            tcx.sess.opts.unstable_opts.mir_include_spans,
+            MirIncludeSpans::On | MirIncludeSpans::Nll
+        ),
+    };
+
+    let dumper = dumper.set_extra_data(extra_data).set_options(options);
+
     let _: io::Result<()> = try {
-        let mut file = create_dump_file(tcx, "html", false, "polonius", &0, body)?;
+        let mut file = dumper.create_dump_file("html", body)?;
         emit_polonius_dump(
-            tcx,
+            &dumper,
             body,
             regioncx,
             borrow_set,
             &polonius_diagnostics.localized_outlives_constraints,
-            closure_region_requirements,
             &mut file,
         )?;
     };
@@ -61,12 +78,11 @@ pub(crate) fn dump_polonius_mir<'tcx>(
 /// - a mermaid graph of the NLL regions and the constraints between them
 /// - a mermaid graph of the NLL SCCs and the constraints between them
 fn emit_polonius_dump<'tcx>(
-    tcx: TyCtxt<'tcx>,
+    dumper: &MirDumper<'_, '_, 'tcx>,
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
-    closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
     out: &mut dyn io::Write,
 ) -> io::Result<()> {
     // Prepare the HTML dump file prologue.
@@ -79,15 +95,7 @@ fn emit_polonius_dump<'tcx>(
     writeln!(out, "<div>")?;
     writeln!(out, "Raw MIR dump")?;
     writeln!(out, "<pre><code>")?;
-    emit_html_mir(
-        tcx,
-        body,
-        regioncx,
-        borrow_set,
-        &localized_outlives_constraints,
-        closure_region_requirements,
-        out,
-    )?;
+    emit_html_mir(dumper, body, out)?;
     writeln!(out, "</code></pre>")?;
     writeln!(out, "</div>")?;
 
@@ -116,7 +124,7 @@ fn emit_polonius_dump<'tcx>(
     writeln!(out, "<div>")?;
     writeln!(out, "NLL regions")?;
     writeln!(out, "<pre class='mermaid'>")?;
-    emit_mermaid_nll_regions(tcx, regioncx, out)?;
+    emit_mermaid_nll_regions(dumper.tcx(), regioncx, out)?;
     writeln!(out, "</pre>")?;
     writeln!(out, "</div>")?;
 
@@ -124,7 +132,7 @@ fn emit_polonius_dump<'tcx>(
     writeln!(out, "<div>")?;
     writeln!(out, "NLL SCCs")?;
     writeln!(out, "<pre class='mermaid'>")?;
-    emit_mermaid_nll_sccs(tcx, regioncx, out)?;
+    emit_mermaid_nll_sccs(dumper.tcx(), regioncx, out)?;
     writeln!(out, "</pre>")?;
     writeln!(out, "</div>")?;
 
@@ -149,45 +157,14 @@ fn emit_polonius_dump<'tcx>(
 
 /// Emits the polonius MIR, as escaped HTML.
 fn emit_html_mir<'tcx>(
-    tcx: TyCtxt<'tcx>,
+    dumper: &MirDumper<'_, '_, 'tcx>,
     body: &Body<'tcx>,
-    regioncx: &RegionInferenceContext<'tcx>,
-    borrow_set: &BorrowSet<'tcx>,
-    localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
-    closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
     out: &mut dyn io::Write,
 ) -> io::Result<()> {
     // Buffer the regular MIR dump to be able to escape it.
     let mut buffer = Vec::new();
 
-    // We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
-    // mir-include-spans` on the CLI still has priority.
-    let options = PrettyPrintMirOptions {
-        include_extra_comments: matches!(
-            tcx.sess.opts.unstable_opts.mir_include_spans,
-            MirIncludeSpans::On | MirIncludeSpans::Nll
-        ),
-    };
-
-    dump_mir_to_writer(
-        tcx,
-        "polonius",
-        &0,
-        body,
-        &mut buffer,
-        &|pass_where, out| {
-            emit_polonius_mir(
-                tcx,
-                regioncx,
-                closure_region_requirements,
-                borrow_set,
-                localized_outlives_constraints,
-                pass_where,
-                out,
-            )
-        },
-        options,
-    )?;
+    dumper.dump_mir_to_writer(body, &mut buffer)?;
 
     // Escape the handful of characters that need it. We don't need to be particularly efficient:
     // we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8.