]>
Commit | Line | Data |
---|---|---|
ff7c6d11 XL |
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 | ||
dfeec247 | 6 | use super::{OutlivesConstraint, RegionInferenceContext}; |
f035d41b | 7 | use crate::borrow_check::type_check::Locations; |
74b04a01 | 8 | use rustc_infer::infer::NLLRegionVariableOrigin; |
f035d41b | 9 | use rustc_middle::ty::TyCtxt; |
ff7c6d11 | 10 | use std::io::{self, Write}; |
ff7c6d11 XL |
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. | |
f035d41b | 19 | pub(crate) fn dump_mir(&self, tcx: TyCtxt<'tcx>, out: &mut dyn Write) -> io::Result<()> { |
ff7c6d11 XL |
20 | writeln!(out, "| Free Region Mapping")?; |
21 | ||
22 | for region in self.regions() { | |
8faf50e0 | 23 | if let NLLRegionVariableOrigin::FreeRegion = self.definitions[region].origin { |
dfeec247 | 24 | let classification = self.universal_regions.region_classification(region).unwrap(); |
8faf50e0 | 25 | let outlived_by = self.universal_region_relations.regions_outlived_by(region); |
ff7c6d11 XL |
26 | writeln!( |
27 | out, | |
0bf4aa26 XL |
28 | "| {r:rw$?} | {c:cw$?} | {ob:?}", |
29 | r = region, | |
ff7c6d11 | 30 | rw = REGION_WIDTH, |
0bf4aa26 | 31 | c = classification, |
ff7c6d11 | 32 | cw = 8, // "External" at most |
0bf4aa26 | 33 | ob = outlived_by |
ff7c6d11 XL |
34 | )?; |
35 | } | |
36 | } | |
37 | ||
38 | writeln!(out, "|")?; | |
39 | writeln!(out, "| Inferred Region Values")?; | |
40 | for region in self.regions() { | |
41 | writeln!( | |
42 | out, | |
0bf4aa26 XL |
43 | "| {r:rw$?} | {ui:4?} | {v}", |
44 | r = region, | |
ff7c6d11 | 45 | rw = REGION_WIDTH, |
8faf50e0 | 46 | ui = self.region_universe(region), |
ff7c6d11 XL |
47 | v = self.region_value_str(region), |
48 | )?; | |
49 | } | |
50 | ||
51 | writeln!(out, "|")?; | |
52 | writeln!(out, "| Inference Constraints")?; | |
f035d41b | 53 | self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?; |
ff7c6d11 XL |
54 | |
55 | Ok(()) | |
56 | } | |
57 | ||
58 | /// Debugging aid: Invokes the `with_msg` callback repeatedly with | |
9fa01778 | 59 | /// our internal region constraints. These are dumped into the |
ff7c6d11 XL |
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, | |
f035d41b | 64 | tcx: TyCtxt<'tcx>, |
0531ce1d | 65 | with_msg: &mut dyn FnMut(&str) -> io::Result<()>, |
ff7c6d11 XL |
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 | ||
dc9dc135 | 74 | let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); |
ff7c6d11 XL |
75 | constraints.sort(); |
76 | for constraint in &constraints { | |
dfeec247 | 77 | let OutlivesConstraint { sup, sub, locations, category } = constraint; |
f035d41b XL |
78 | let (name, arg) = match locations { |
79 | Locations::All(span) => ("All", tcx.sess.source_map().span_to_string(*span)), | |
80 | Locations::Single(loc) => ("Single", format!("{:?}", loc)), | |
81 | }; | |
82 | with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?; | |
ff7c6d11 XL |
83 | } |
84 | ||
85 | Ok(()) | |
86 | } | |
87 | } |