rustc_borrowck/region_infer/
reverse_sccs.rs
1use std::ops::Range;
2
3use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
4use rustc_data_structures::graph;
5use rustc_data_structures::graph::vec_graph::VecGraph;
6use rustc_middle::ty::RegionVid;
7
8use crate::RegionInferenceContext;
9use crate::constraints::ConstraintSccIndex;
10
11pub(crate) struct ReverseSccGraph {
12 graph: VecGraph<ConstraintSccIndex>,
13 scc_regions: FxIndexMap<ConstraintSccIndex, Range<usize>>,
16 universal_regions: Vec<RegionVid>,
19}
20
21impl ReverseSccGraph {
22 pub(super) fn upper_bounds<'a>(
24 &'a self,
25 scc0: ConstraintSccIndex,
26 ) -> impl Iterator<Item = RegionVid> + 'a {
27 let mut duplicates = FxIndexSet::default();
28 graph::depth_first_search(&self.graph, scc0)
29 .flat_map(move |scc1| {
30 self.scc_regions
31 .get(&scc1)
32 .map_or(&[][..], |range| &self.universal_regions[range.clone()])
33 })
34 .copied()
35 .filter(move |r| duplicates.insert(*r))
36 }
37}
38
39impl RegionInferenceContext<'_> {
40 pub(super) fn compute_reverse_scc_graph(&mut self) {
42 if self.rev_scc_graph.is_some() {
43 return;
44 }
45
46 let graph = self.constraint_sccs.reverse();
47 let mut paired_scc_regions = self
48 .universal_regions()
49 .universal_regions_iter()
50 .map(|region| (self.constraint_sccs.scc(region), region))
51 .collect::<Vec<_>>();
52 paired_scc_regions.sort();
53 let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
54
55 let mut scc_regions = FxIndexMap::default();
56 let mut start = 0;
57 for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) {
58 let (scc, _) = chunk[0];
59 scc_regions.insert(scc, start..start + chunk.len());
60 start += chunk.len();
61 }
62
63 self.rev_scc_graph = Some(ReverseSccGraph { graph, scc_regions, universal_regions });
64 }
65}