@@ -12,9 +12,6 @@ use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSe
12
12
use crate::{BorrowckInferCtxt, RegionInferenceContext};
13
13
14
14
/// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
15
- // Note: this currently duplicates most of NLL MIR, with some additions for the localized outlives
16
- // constraints. This is ok for now as this dump will change in the near future to an HTML file to
17
- // become more useful.
18
15
pub(crate) fn dump_polonius_mir<'tcx>(
19
16
infcx: &BorrowckInferCtxt<'tcx>,
20
17
body: &Body<'tcx>,
@@ -36,7 +33,7 @@ pub(crate) fn dump_polonius_mir<'tcx>(
36
33
.expect("missing localized constraints with `-Zpolonius=next`");
37
34
38
35
let _: io::Result<()> = try {
39
- let mut file = create_dump_file(tcx, "mir ", false, "polonius", &0, body)?;
36
+ let mut file = create_dump_file(tcx, "html ", false, "polonius", &0, body)?;
40
37
emit_polonius_dump(
41
38
tcx,
42
39
body,
@@ -61,9 +58,50 @@ fn emit_polonius_dump<'tcx>(
61
58
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
62
59
out: &mut dyn io::Write,
63
60
) -> io::Result<()> {
64
- // We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in
65
- // #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example,
66
- // they're always disabled in mir-opt tests to make working with blessed dumps easier.
61
+ // Prepare the HTML dump file prologue.
62
+ writeln!(out, "<!DOCTYPE html>")?;
63
+ writeln!(out, "<html>")?;
64
+ writeln!(out, "<head><title>Polonius MIR dump</title></head>")?;
65
+ writeln!(out, "<body>")?;
66
+
67
+ // Section 1: the NLL + Polonius MIR.
68
+ writeln!(out, "<div>")?;
69
+ writeln!(out, "Raw MIR dump")?;
70
+ writeln!(out, "<code><pre>")?;
71
+ emit_html_mir(
72
+ tcx,
73
+ body,
74
+ regioncx,
75
+ borrow_set,
76
+ localized_outlives_constraints,
77
+ closure_region_requirements,
78
+ out,
79
+ )?;
80
+ writeln!(out, "</pre></code>")?;
81
+ writeln!(out, "</div>")?;
82
+
83
+ // Finalize the dump with the HTML epilogue.
84
+ writeln!(out, "</body>")?;
85
+ writeln!(out, "</html>")?;
86
+
87
+ Ok(())
88
+ }
89
+
90
+ /// Emits the polonius MIR, as escaped HTML.
91
+ fn emit_html_mir<'tcx>(
92
+ tcx: TyCtxt<'tcx>,
93
+ body: &Body<'tcx>,
94
+ regioncx: &RegionInferenceContext<'tcx>,
95
+ borrow_set: &BorrowSet<'tcx>,
96
+ localized_outlives_constraints: LocalizedOutlivesConstraintSet,
97
+ closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
98
+ out: &mut dyn io::Write,
99
+ ) -> io::Result<()> {
100
+ // Buffer the regular MIR dump to be able to escape it.
101
+ let mut buffer = Vec::new();
102
+
103
+ // We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
104
+ // mir-include-spans` on the CLI still has priority.
67
105
let options = PrettyPrintMirOptions {
68
106
include_extra_comments: matches!(
69
107
tcx.sess.opts.unstable_opts.mir_include_spans,
@@ -76,7 +114,7 @@ fn emit_polonius_dump<'tcx>(
76
114
"polonius",
77
115
&0,
78
116
body,
79
- out ,
117
+ &mut buffer ,
80
118
|pass_where, out| {
81
119
emit_polonius_mir(
82
120
tcx,
@@ -89,7 +127,27 @@ fn emit_polonius_dump<'tcx>(
89
127
)
90
128
},
91
129
options,
92
- )
130
+ )?;
131
+
132
+ // Escape the handful of characters that need it. We don't need to be particularly efficient:
133
+ // we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8.
134
+ let buffer = String::from_utf8_lossy(&buffer);
135
+ for ch in buffer.chars() {
136
+ let escaped = match ch {
137
+ '>' => ">",
138
+ '<' => "<",
139
+ '&' => "&",
140
+ '\'' => "'",
141
+ '"' => """,
142
+ _ => {
143
+ // The common case, no escaping needed.
144
+ write!(out, "{}", ch)?;
145
+ continue;
146
+ }
147
+ };
148
+ write!(out, "{}", escaped)?;
149
+ }
150
+ Ok(())
93
151
}
94
152
95
153
/// Produces the actual NLL + Polonius MIR sections to emit during the dumping process.
0 commit comments