rustc_borrowck/region_infer/opaque_types/
region_ctxt.rs

1use std::rc::Rc;
2
3use rustc_data_structures::frozen::Frozen;
4use rustc_index::IndexVec;
5use rustc_infer::infer::NllRegionVariableOrigin;
6use rustc_middle::ty::{RegionVid, UniverseIndex};
7use rustc_mir_dataflow::points::DenseLocationMap;
8
9use crate::BorrowckInferCtxt;
10use crate::constraints::ConstraintSccIndex;
11use crate::handle_placeholders::{SccAnnotations, region_definitions};
12use crate::region_infer::reverse_sccs::ReverseSccGraph;
13use crate::region_infer::values::RegionValues;
14use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker, Representative};
15use crate::type_check::MirTypeckRegionConstraints;
16use crate::type_check::free_region_relations::UniversalRegionRelations;
17use crate::universal_regions::UniversalRegions;
18
19/// A slimmed down version of [crate::region_infer::RegionInferenceContext] used
20/// only by opaque type handling.
21pub(super) struct RegionCtxt<'a, 'tcx> {
22    pub(super) infcx: &'a BorrowckInferCtxt<'tcx>,
23    pub(super) definitions: Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>,
24    pub(super) universal_region_relations: &'a UniversalRegionRelations<'tcx>,
25    pub(super) constraint_sccs: ConstraintSccs,
26    pub(super) scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
27    pub(super) rev_scc_graph: ReverseSccGraph,
28    pub(super) scc_values: RegionValues<ConstraintSccIndex>,
29}
30
31impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
32    /// Creates a new `RegionCtxt` used to compute defining opaque type uses.
33    ///
34    /// This does not yet propagate region values. This is instead done lazily
35    /// when applying member constraints.
36    pub(super) fn new(
37        infcx: &'a BorrowckInferCtxt<'tcx>,
38        universal_region_relations: &'a Frozen<UniversalRegionRelations<'tcx>>,
39        location_map: Rc<DenseLocationMap>,
40        constraints: &MirTypeckRegionConstraints<'tcx>,
41    ) -> RegionCtxt<'a, 'tcx> {
42        let universal_regions = &universal_region_relations.universal_regions;
43        let (definitions, _has_placeholders) = region_definitions(infcx, universal_regions);
44        let mut scc_annotations = SccAnnotations::init(&definitions);
45        let constraint_sccs = ConstraintSccs::new_with_annotation(
46            &constraints
47                .outlives_constraints
48                .graph(definitions.len())
49                .region_graph(&constraints.outlives_constraints, universal_regions.fr_static),
50            &mut scc_annotations,
51        );
52        let scc_annotations = scc_annotations.scc_to_annotation;
53
54        // Unlike the `RegionInferenceContext`, we only care about free regions
55        // and fully ignore liveness and placeholders.
56        let placeholder_indices = Default::default();
57        let mut scc_values =
58            RegionValues::new(location_map, universal_regions.len(), placeholder_indices);
59        for variable in definitions.indices() {
60            let scc = constraint_sccs.scc(variable);
61            match definitions[variable].origin {
62                NllRegionVariableOrigin::FreeRegion => {
63                    scc_values.add_element(scc, variable);
64                }
65                _ => {}
66            }
67        }
68
69        let rev_scc_graph = ReverseSccGraph::compute(&constraint_sccs, universal_regions);
70        RegionCtxt {
71            infcx,
72            definitions,
73            universal_region_relations,
74            constraint_sccs,
75            scc_annotations,
76            rev_scc_graph,
77            scc_values,
78        }
79    }
80
81    pub(super) fn representative(&self, vid: RegionVid) -> Representative {
82        let scc = self.constraint_sccs.scc(vid);
83        self.scc_annotations[scc].representative
84    }
85
86    pub(crate) fn max_placeholder_universe_reached(
87        &self,
88        scc: ConstraintSccIndex,
89    ) -> UniverseIndex {
90        self.scc_annotations[scc].max_placeholder_universe_reached()
91    }
92
93    pub(super) fn universal_regions(&self) -> &UniversalRegions<'tcx> {
94        &self.universal_region_relations.universal_regions
95    }
96
97    pub(super) fn eval_equal(&self, r1_vid: RegionVid, r2_vid: RegionVid) -> bool {
98        let r1 = self.constraint_sccs.scc(r1_vid);
99        let r2 = self.constraint_sccs.scc(r2_vid);
100
101        if r1 == r2 {
102            return true;
103        }
104
105        let universal_outlives = |sub, sup| {
106            self.scc_values.universal_regions_outlived_by(sub).all(|r1| {
107                self.scc_values
108                    .universal_regions_outlived_by(sup)
109                    .any(|r2| self.universal_region_relations.outlives(r2, r1))
110            })
111        };
112        universal_outlives(r1, r2) && universal_outlives(r2, r1)
113    }
114}