rustc_borrowck/region_infer/opaque_types/
region_ctxt.rs1use 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
21pub(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 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 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}