Skip to content

Commit c75c517

Browse files
committed
introduce beginnings of polonius MIR dump
This is mostly for test purposes to show the localized constraints until the MIR debugger is set up.
1 parent ee93ce9 commit c75c517

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

compiler/rustc_borrowck/src/lib.rs

+10
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,16 @@ fn do_mir_borrowck<'tcx>(
316316

317317
mbcx.report_move_errors();
318318

319+
// If requested, dump polonius MIR.
320+
polonius::dump_polonius_mir(
321+
&infcx,
322+
body,
323+
&regioncx,
324+
&borrow_set,
325+
&localized_outlives_constraints,
326+
&opt_closure_req,
327+
);
328+
319329
// For each non-user used mutable variable, check if it's been assigned from
320330
// a user-declared local. If so, then put that local into the used_mut set.
321331
// Note that this set is expected to be small - only upvars from closures
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use std::io;
2+
3+
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
4+
use rustc_middle::mir::{Body, ClosureRegionRequirements, PassWhere};
5+
use rustc_middle::ty::TyCtxt;
6+
use rustc_session::config::MirIncludeSpans;
7+
8+
use crate::borrow_set::BorrowSet;
9+
use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet};
10+
use crate::{BorrowckInferCtxt, RegionInferenceContext};
11+
12+
/// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
13+
// Note: this currently duplicates most of NLL MIR, with some additions for the localized outlives
14+
// constraints. This is ok for now as this dump will change in the near future to an HTML file to
15+
// become more useful.
16+
pub(crate) fn dump_polonius_mir<'tcx>(
17+
infcx: &BorrowckInferCtxt<'tcx>,
18+
body: &Body<'tcx>,
19+
regioncx: &RegionInferenceContext<'tcx>,
20+
borrow_set: &BorrowSet<'tcx>,
21+
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
22+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
23+
) {
24+
let tcx = infcx.tcx;
25+
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
26+
return;
27+
}
28+
29+
// We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in
30+
// #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example,
31+
// they're always disabled in mir-opt tests to make working with blessed dumps easier.
32+
let options = PrettyPrintMirOptions {
33+
include_extra_comments: matches!(
34+
tcx.sess.opts.unstable_opts.mir_include_spans,
35+
MirIncludeSpans::On | MirIncludeSpans::Nll
36+
),
37+
};
38+
39+
dump_mir_with_options(
40+
tcx,
41+
false,
42+
"polonius",
43+
&0,
44+
body,
45+
|pass_where, out| {
46+
emit_polonius_mir(
47+
tcx,
48+
regioncx,
49+
closure_region_requirements,
50+
borrow_set,
51+
localized_outlives_constraints,
52+
pass_where,
53+
out,
54+
)
55+
},
56+
options,
57+
);
58+
}
59+
60+
/// Produces the actual NLL + Polonius MIR sections to emit during the dumping process.
61+
fn emit_polonius_mir<'tcx>(
62+
tcx: TyCtxt<'tcx>,
63+
regioncx: &RegionInferenceContext<'tcx>,
64+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
65+
borrow_set: &BorrowSet<'tcx>,
66+
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
67+
pass_where: PassWhere,
68+
out: &mut dyn io::Write,
69+
) -> io::Result<()> {
70+
// Emit the regular NLL front-matter
71+
crate::nll::emit_nll_mir(
72+
tcx,
73+
regioncx,
74+
closure_region_requirements,
75+
borrow_set,
76+
pass_where.clone(),
77+
out,
78+
)?;
79+
80+
let liveness = regioncx.liveness_constraints();
81+
82+
// Add localized outlives constraints
83+
match pass_where {
84+
PassWhere::BeforeCFG => {
85+
if localized_outlives_constraints.outlives.len() > 0 {
86+
writeln!(out, "| Localized constraints")?;
87+
88+
for constraint in &localized_outlives_constraints.outlives {
89+
let LocalizedOutlivesConstraint { source, from, target, to } = constraint;
90+
let from = liveness.location_from_point(*from);
91+
let to = liveness.location_from_point(*to);
92+
writeln!(out, "| {source:?} at {from:?} -> {target:?} at {to:?}")?;
93+
}
94+
writeln!(out, "|")?;
95+
}
96+
}
97+
_ => {}
98+
}
99+
100+
Ok(())
101+
}

compiler/rustc_borrowck/src/polonius/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
3636
mod constraints;
3737
pub(crate) use constraints::*;
38+
mod dump;
39+
pub(crate) use dump::dump_polonius_mir;
3840
pub(crate) mod legacy;
3941

4042
use rustc_middle::mir::{Body, Location};

compiler/rustc_borrowck/src/region_infer/values.rs

+5
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ impl LivenessValues {
199199
self.elements.point_from_location(location)
200200
}
201201

202+
#[inline]
203+
pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
204+
self.elements.to_location(point)
205+
}
206+
202207
/// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
203208
pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
204209
self.loans

0 commit comments

Comments
 (0)