diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-08-15 14:38:17 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-09-01 09:19:03 +1000 |
| commit | 5ce3797073ee5e6cc487b80effbc682533d9425c (patch) | |
| tree | 06a143d06ef4deed8856880424c3ff824cdbf756 /compiler/rustc_borrowck | |
| parent | 2d21c134054b6d337d4a1b81550a1ad10509b913 (diff) | |
| download | rust-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.rs | 35 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/polonius/dump.rs | 87 |
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. |
