|
1 | 1 | use rustc_data_structures::graph;
|
2 | 2 | use rustc_index::IndexVec;
|
3 |
| -use rustc_middle::mir::ConstraintCategory; |
4 |
| -use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; |
5 |
| -use rustc_span::DUMMY_SP; |
| 3 | +use rustc_middle::ty::RegionVid; |
6 | 4 |
|
7 | 5 | use crate::constraints::{OutlivesConstraint, OutlivesConstraintIndex, OutlivesConstraintSet};
|
8 |
| -use crate::type_check::Locations; |
9 | 6 |
|
10 | 7 | /// The construct graph organizes the constraints by their end-points.
|
11 | 8 | /// It can be used to view a `R1: R2` constraint as either an edge `R1
|
@@ -105,63 +102,57 @@ impl<D: ConstraintGraphDirection> ConstraintGraph<D> {
|
105 | 102 | RegionGraph::new(set, self, static_region)
|
106 | 103 | }
|
107 | 104 |
|
| 105 | + pub(crate) fn is_normal(&self) -> bool { |
| 106 | + D::is_normal() |
| 107 | + } |
| 108 | + |
108 | 109 | /// Given a region `R`, iterate over all constraints `R: R1`.
|
109 |
| - pub(crate) fn outgoing_edges<'a, 'tcx>( |
| 110 | + pub(crate) fn outgoing_edges_from_graph<'a, 'tcx>( |
110 | 111 | &'a self,
|
111 | 112 | region_sup: RegionVid,
|
112 | 113 | constraints: &'a OutlivesConstraintSet<'tcx>,
|
113 |
| - static_region: RegionVid, |
114 |
| - ) -> Edges<'a, 'tcx, D> { |
115 |
| - //if this is the `'static` region and the graph's direction is normal, |
116 |
| - //then setup the Edges iterator to return all regions #53178 |
117 |
| - if region_sup == static_region && D::is_normal() { |
118 |
| - Edges { |
119 |
| - graph: self, |
120 |
| - constraints, |
121 |
| - pointer: None, |
122 |
| - next_static_idx: Some(0), |
123 |
| - static_region, |
124 |
| - } |
125 |
| - } else { |
126 |
| - //otherwise, just setup the iterator as normal |
127 |
| - let first = self.first_constraints[region_sup]; |
128 |
| - Edges { graph: self, constraints, pointer: first, next_static_idx: None, static_region } |
129 |
| - } |
| 114 | + ) -> EdgesFromGraph<'a, 'tcx, D> { |
| 115 | + EdgesFromGraph { graph: self, constraints, pointer: self.first_constraints[region_sup] } |
| 116 | + } |
| 117 | + |
| 118 | + /// Returns all regions (#53178). |
| 119 | + pub(crate) fn outgoing_edges_from_static(&self) -> EdgesFromStatic { |
| 120 | + EdgesFromStatic { next_static_idx: 0, end_static_idx: self.first_constraints.len() } |
130 | 121 | }
|
131 | 122 | }
|
132 | 123 |
|
133 |
| -pub(crate) struct Edges<'a, 'tcx, D: ConstraintGraphDirection> { |
| 124 | +pub(crate) struct EdgesFromGraph<'a, 'tcx, D: ConstraintGraphDirection> { |
134 | 125 | graph: &'a ConstraintGraph<D>,
|
135 | 126 | constraints: &'a OutlivesConstraintSet<'tcx>,
|
136 | 127 | pointer: Option<OutlivesConstraintIndex>,
|
137 |
| - next_static_idx: Option<usize>, |
138 |
| - static_region: RegionVid, |
139 | 128 | }
|
140 | 129 |
|
141 |
| -impl<'a, 'tcx, D: ConstraintGraphDirection> Iterator for Edges<'a, 'tcx, D> { |
142 |
| - type Item = OutlivesConstraint<'tcx>; |
| 130 | +impl<'a, 'tcx, D: ConstraintGraphDirection> Iterator for EdgesFromGraph<'a, 'tcx, D> { |
| 131 | + type Item = &'a OutlivesConstraint<'tcx>; |
143 | 132 |
|
144 | 133 | fn next(&mut self) -> Option<Self::Item> {
|
145 | 134 | if let Some(p) = self.pointer {
|
146 | 135 | self.pointer = self.graph.next_constraints[p];
|
| 136 | + Some(&self.constraints[p]) |
| 137 | + } else { |
| 138 | + None |
| 139 | + } |
| 140 | + } |
| 141 | +} |
| 142 | + |
| 143 | +pub(crate) struct EdgesFromStatic { |
| 144 | + next_static_idx: usize, |
| 145 | + end_static_idx: usize, |
| 146 | +} |
| 147 | + |
| 148 | +impl Iterator for EdgesFromStatic { |
| 149 | + type Item = RegionVid; |
147 | 150 |
|
148 |
| - Some(self.constraints[p]) |
149 |
| - } else if let Some(next_static_idx) = self.next_static_idx { |
150 |
| - self.next_static_idx = if next_static_idx == (self.graph.first_constraints.len() - 1) { |
151 |
| - None |
152 |
| - } else { |
153 |
| - Some(next_static_idx + 1) |
154 |
| - }; |
155 |
| - |
156 |
| - Some(OutlivesConstraint { |
157 |
| - sup: self.static_region, |
158 |
| - sub: next_static_idx.into(), |
159 |
| - locations: Locations::All(DUMMY_SP), |
160 |
| - span: DUMMY_SP, |
161 |
| - category: ConstraintCategory::Internal, |
162 |
| - variance_info: VarianceDiagInfo::default(), |
163 |
| - from_closure: false, |
164 |
| - }) |
| 151 | + fn next(&mut self) -> Option<Self::Item> { |
| 152 | + if self.next_static_idx < self.end_static_idx { |
| 153 | + let ret = RegionVid::from_usize(self.next_static_idx); |
| 154 | + self.next_static_idx += 1; |
| 155 | + Some(ret) |
165 | 156 | } else {
|
166 | 157 | None
|
167 | 158 | }
|
@@ -193,21 +184,38 @@ impl<'a, 'tcx, D: ConstraintGraphDirection> RegionGraph<'a, 'tcx, D> {
|
193 | 184 | /// Given a region `R`, iterate over all regions `R1` such that
|
194 | 185 | /// there exists a constraint `R: R1`.
|
195 | 186 | pub(crate) fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'a, 'tcx, D> {
|
196 |
| - Successors { |
197 |
| - edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region), |
| 187 | + // If this is the `'static` region and the graph's direction is normal, |
| 188 | + // then setup the Edges iterator to return all regions (#53178). |
| 189 | + if region_sup == self.static_region && D::is_normal() { |
| 190 | + Successors::FromStatic(self.constraint_graph.outgoing_edges_from_static()) |
| 191 | + } else { |
| 192 | + // Otherwise, just setup the iterator as normal. |
| 193 | + Successors::FromGraph( |
| 194 | + self.constraint_graph.outgoing_edges_from_graph(region_sup, self.set), |
| 195 | + ) |
198 | 196 | }
|
199 | 197 | }
|
200 | 198 | }
|
201 | 199 |
|
202 |
| -pub(crate) struct Successors<'a, 'tcx, D: ConstraintGraphDirection> { |
203 |
| - edges: Edges<'a, 'tcx, D>, |
| 200 | +pub(crate) enum Successors<'a, 'tcx, D: ConstraintGraphDirection> { |
| 201 | + FromStatic(EdgesFromStatic), |
| 202 | + FromGraph(EdgesFromGraph<'a, 'tcx, D>), |
204 | 203 | }
|
205 | 204 |
|
206 | 205 | impl<'a, 'tcx, D: ConstraintGraphDirection> Iterator for Successors<'a, 'tcx, D> {
|
207 | 206 | type Item = RegionVid;
|
208 | 207 |
|
209 | 208 | fn next(&mut self) -> Option<Self::Item> {
|
210 |
| - self.edges.next().map(|c| D::end_region(c.sup, c.sub)) |
| 209 | + match self { |
| 210 | + Successors::FromStatic(edges) => { |
| 211 | + // No `D::end_region` call needed here: static successors are only possible when |
| 212 | + // the direction is `Normal`, so we can directly use what would be the `sub` value. |
| 213 | + edges.next() |
| 214 | + } |
| 215 | + Successors::FromGraph(edges) => { |
| 216 | + edges.next().map(|constraint| D::end_region(constraint.sup, constraint.sub)) |
| 217 | + } |
| 218 | + } |
211 | 219 | }
|
212 | 220 | }
|
213 | 221 |
|
|
0 commit comments