]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs
Rollup merge of #85174 - GuillaumeGomez:doc-code-block-border-radius, r=jsha
[rust.git] / compiler / rustc_mir / src / borrow_check / region_infer / dump_mir.rs
1 //! As part of generating the regions, if you enable `-Zdump-mir=nll`,
2 //! we will generate an annotated copy of the MIR that includes the
3 //! state of region inference. This code handles emitting the region
4 //! context internal state.
5
6 use super::{OutlivesConstraint, RegionInferenceContext};
7 use crate::borrow_check::type_check::Locations;
8 use rustc_infer::infer::NllRegionVariableOrigin;
9 use rustc_middle::ty::TyCtxt;
10 use std::io::{self, Write};
11
12 // Room for "'_#NNNNr" before things get misaligned.
13 // Easy enough to fix if this ever doesn't seem like
14 // enough.
15 const REGION_WIDTH: usize = 8;
16
17 impl<'tcx> RegionInferenceContext<'tcx> {
18     /// Write out our state into the `.mir` files.
19     pub(crate) fn dump_mir(&self, tcx: TyCtxt<'tcx>, out: &mut dyn Write) -> io::Result<()> {
20         writeln!(out, "| Free Region Mapping")?;
21
22         for region in self.regions() {
23             if let NllRegionVariableOrigin::FreeRegion = self.definitions[region].origin {
24                 let classification = self.universal_regions.region_classification(region).unwrap();
25                 let outlived_by = self.universal_region_relations.regions_outlived_by(region);
26                 writeln!(
27                     out,
28                     "| {r:rw$?} | {c:cw$?} | {ob:?}",
29                     r = region,
30                     rw = REGION_WIDTH,
31                     c = classification,
32                     cw = 8, // "External" at most
33                     ob = outlived_by
34                 )?;
35             }
36         }
37
38         writeln!(out, "|")?;
39         writeln!(out, "| Inferred Region Values")?;
40         for region in self.regions() {
41             writeln!(
42                 out,
43                 "| {r:rw$?} | {ui:4?} | {v}",
44                 r = region,
45                 rw = REGION_WIDTH,
46                 ui = self.region_universe(region),
47                 v = self.region_value_str(region),
48             )?;
49         }
50
51         writeln!(out, "|")?;
52         writeln!(out, "| Inference Constraints")?;
53         self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?;
54
55         Ok(())
56     }
57
58     /// Debugging aid: Invokes the `with_msg` callback repeatedly with
59     /// our internal region constraints. These are dumped into the
60     /// -Zdump-mir file so that we can figure out why the region
61     /// inference resulted in the values that it did when debugging.
62     fn for_each_constraint(
63         &self,
64         tcx: TyCtxt<'tcx>,
65         with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
66     ) -> io::Result<()> {
67         for region in self.definitions.indices() {
68             let value = self.liveness_constraints.region_value_str(region);
69             if value != "{}" {
70                 with_msg(&format!("{:?} live at {}", region, value))?;
71             }
72         }
73
74         let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
75         constraints.sort();
76         for constraint in &constraints {
77             let OutlivesConstraint { sup, sub, locations, category } = constraint;
78             let (name, arg) = match locations {
79                 Locations::All(span) => {
80                     ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
81                 }
82                 Locations::Single(loc) => ("Single", format!("{:?}", loc)),
83             };
84             with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?;
85         }
86
87         Ok(())
88     }
89 }