blob: e8da85eccef16ac4584613a8898c43c096aef1b7 [file] [log] [blame]
use std::ops::Range;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph;
use rustc_data_structures::graph::vec_graph::VecGraph;
use rustc_middle::ty::RegionVid;
use crate::constraints::ConstraintSccIndex;
use crate::region_infer::ConstraintSccs;
use crate::universal_regions::UniversalRegions;
pub(crate) struct ReverseSccGraph {
graph: VecGraph<ConstraintSccIndex>,
/// For each SCC, the range of `universal_regions` that use that SCC as
/// their value.
scc_regions: FxIndexMap<ConstraintSccIndex, Range<usize>>,
/// All of the universal regions, in grouped so that `scc_regions` can
/// index into here.
universal_regions: Vec<RegionVid>,
}
impl ReverseSccGraph {
pub(super) fn compute(
constraint_sccs: &ConstraintSccs,
universal_regions: &UniversalRegions<'_>,
) -> Self {
let graph = constraint_sccs.reverse();
let mut paired_scc_regions = universal_regions
.universal_regions_iter()
.map(|region| (constraint_sccs.scc(region), region))
.collect::<Vec<_>>();
paired_scc_regions.sort();
let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
let mut scc_regions = FxIndexMap::default();
let mut start = 0;
for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) {
let (scc, _) = chunk[0];
scc_regions.insert(scc, start..start + chunk.len());
start += chunk.len();
}
ReverseSccGraph { graph, scc_regions, universal_regions }
}
/// Find all universal regions that are required to outlive the given SCC.
pub(super) fn upper_bounds(&self, scc0: ConstraintSccIndex) -> impl Iterator<Item = RegionVid> {
let mut duplicates = FxIndexSet::default();
graph::depth_first_search(&self.graph, scc0)
.flat_map(move |scc1| {
self.scc_regions
.get(&scc1)
.map_or(&[][..], |range| &self.universal_regions[range.clone()])
})
.copied()
.filter(move |r| duplicates.insert(*r))
}
}