Skip to main content

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