//! As part of generating the regions, if you enable `-Zdump-mir=nll`,
//! we will generate an annotated copy of the MIR that includes the
//! state of region inference. This code handles emitting the region
//! context internal state.

use rustc::infer::NLLRegionVariableOrigin;
use std::io::{self, Write};
use super::{OutlivesConstraint, RegionInferenceContext};

// Room for "'_#NNNNr" before things get misaligned.
// Easy enough to fix if this ever doesn't seem like
// enough.
const REGION_WIDTH: usize = 8;

impl<'tcx> RegionInferenceContext<'tcx> {
    /// Write out our state into the `.mir` files.
    pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> {
        writeln!(out, "| Free Region Mapping")?;

        for region in self.regions() {
            if let NLLRegionVariableOrigin::FreeRegion = self.definitions[region].origin {
                let classification = self
                    .universal_regions
                    .region_classification(region)
                    .unwrap();
                let outlived_by = self.universal_region_relations.regions_outlived_by(region);
                writeln!(
                    out,
                    "| {r:rw$?} | {c:cw$?} | {ob:?}",
                    r = region,
                    rw = REGION_WIDTH,
                    c = classification,
                    cw = 8, // "External" at most
                    ob = outlived_by
                )?;
            }
        }

        writeln!(out, "|")?;
        writeln!(out, "| Inferred Region Values")?;
        for region in self.regions() {
            writeln!(
                out,
                "| {r:rw$?} | {ui:4?} | {v}",
                r = region,
                rw = REGION_WIDTH,
                ui = self.region_universe(region),
                v = self.region_value_str(region),
            )?;
        }

        writeln!(out, "|")?;
        writeln!(out, "| Inference Constraints")?;
        self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?;

        Ok(())
    }

    /// Debugging aid: Invokes the `with_msg` callback repeatedly with
    /// our internal region constraints. These are dumped into the
    /// -Zdump-mir file so that we can figure out why the region
    /// inference resulted in the values that it did when debugging.
    fn for_each_constraint(
        &self,
        with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
    ) -> io::Result<()> {
        for region in self.definitions.indices() {
            let value = self.liveness_constraints.region_value_str(region);
            if value != "{}" {
                with_msg(&format!("{:?} live at {}", region, value))?;
            }
        }

        let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
        constraints.sort();
        for constraint in &constraints {
            let OutlivesConstraint {
                sup,
                sub,
                locations,
                category,
            } = constraint;
            with_msg(&format!(
                "{:?}: {:?} due to {:?} at {:?}",
                sup,
                sub,
                category,
                locations,
            ))?;
        }

        Ok(())
    }
}
