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.
6 use super::{OutlivesConstraint, RegionInferenceContext};
7 use crate::type_check::Locations;
8 use rustc_infer::infer::NllRegionVariableOrigin;
9 use rustc_middle::ty::TyCtxt;
10 use std::io::{self, Write};
12 // Room for "'_#NNNNr" before things get misaligned.
13 // Easy enough to fix if this ever doesn't seem like
15 const REGION_WIDTH: usize = 8;
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")?;
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);
28 "| {r:rw$?} | {c:cw$?} | {ob:?}",
32 cw = 8, // "External" at most
39 writeln!(out, "| Inferred Region Values")?;
40 for region in self.regions() {
43 "| {r:rw$?} | {ui:4?} | {v}",
46 ui = self.region_universe(region),
47 v = self.region_value_str(region),
52 writeln!(out, "| Inference Constraints")?;
53 self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?;
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(
65 with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
67 for region in self.definitions.indices() {
68 let value = self.liveness_constraints.region_value_str(region);
70 with_msg(&format!("{:?} live at {}", region, value))?;
74 let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
75 constraints.sort_by_key(|c| (c.sup, c.sub));
76 for constraint in &constraints {
77 let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
78 let (name, arg) = match locations {
79 Locations::All(span) => {
80 ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
82 Locations::Single(loc) => ("Single", format!("{:?}", loc)),
85 "{:?}: {:?} due to {:?} at {}({}) ({:?}",
86 sup, sub, category, name, arg, span