@@ -311,9 +311,11 @@ enum RegionRelationCheckResult {
311
311
}
312
312
313
313
#[derive(Clone, PartialEq, Eq, Debug)]
314
- enum Trace<'tcx> {
314
+ enum Trace<'a, ' tcx> {
315
315
StartRegion,
316
- FromOutlivesConstraint(OutlivesConstraint<'tcx>),
316
+ FromGraph(&'a OutlivesConstraint<'tcx>),
317
+ FromStatic(RegionVid),
318
+ FromMember(RegionVid, RegionVid, Span),
317
319
NotVisited,
318
320
}
319
321
@@ -1764,6 +1766,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1764
1766
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
1765
1767
context[from_region] = Trace::StartRegion;
1766
1768
1769
+ let fr_static = self.universal_regions().fr_static;
1770
+
1767
1771
// Use a deque so that we do a breadth-first search. We will
1768
1772
// stop at the first match, which ought to be the shortest
1769
1773
// path (fewest constraints).
@@ -1783,13 +1787,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1783
1787
if target_test(r) {
1784
1788
let mut result = vec![];
1785
1789
let mut p = r;
1790
+ // This loop is cold and runs at the end, which is why we delay
1791
+ // `OutlivesConstraint` construction until now.
1786
1792
loop {
1787
- match context[p].clone() {
1788
- Trace::NotVisited => {
1789
- bug!("found unvisited region {:?} on path to {:?}", p, r)
1793
+ match context[p] {
1794
+ Trace::FromGraph(c) => {
1795
+ p = c.sup;
1796
+ result.push(*c);
1790
1797
}
1791
1798
1792
- Trace::FromOutlivesConstraint(c) => {
1799
+ Trace::FromStatic(sub) => {
1800
+ let c = OutlivesConstraint {
1801
+ sup: fr_static,
1802
+ sub,
1803
+ locations: Locations::All(DUMMY_SP),
1804
+ span: DUMMY_SP,
1805
+ category: ConstraintCategory::Internal,
1806
+ variance_info: ty::VarianceDiagInfo::default(),
1807
+ from_closure: false,
1808
+ };
1809
+ p = c.sup;
1810
+ result.push(c);
1811
+ }
1812
+
1813
+ Trace::FromMember(sup, sub, span) => {
1814
+ let c = OutlivesConstraint {
1815
+ sup,
1816
+ sub,
1817
+ locations: Locations::All(span),
1818
+ span,
1819
+ category: ConstraintCategory::OpaqueType,
1820
+ variance_info: ty::VarianceDiagInfo::default(),
1821
+ from_closure: false,
1822
+ };
1793
1823
p = c.sup;
1794
1824
result.push(c);
1795
1825
}
@@ -1798,6 +1828,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1798
1828
result.reverse();
1799
1829
return Some((result, r));
1800
1830
}
1831
+
1832
+ Trace::NotVisited => {
1833
+ bug!("found unvisited region {:?} on path to {:?}", p, r)
1834
+ }
1801
1835
}
1802
1836
}
1803
1837
}
@@ -1808,33 +1842,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1808
1842
1809
1843
// A constraint like `'r: 'x` can come from our constraint
1810
1844
// graph.
1811
- let fr_static = self.universal_regions().fr_static;
1812
1845
1813
1846
// Always inline this closure because it can be hot.
1814
- let mut handle_constraint = #[inline(always)]
1815
- |constraint: &OutlivesConstraint<'tcx>| {
1816
- debug_assert_eq!(constraint.sup, r);
1817
- let sub_region = constraint.sub;
1818
- if let Trace::NotVisited = context[sub_region] {
1819
- context[sub_region] = Trace::FromOutlivesConstraint(*constraint);
1820
- deque.push_back(sub_region);
1847
+ let mut handle_trace = #[inline(always)]
1848
+ |sub, trace| {
1849
+ if let Trace::NotVisited = context[sub] {
1850
+ context[sub] = trace;
1851
+ deque.push_back(sub);
1821
1852
}
1822
1853
};
1823
1854
1824
1855
// If this is the `'static` region and the graph's direction is normal, then set up the
1825
1856
// Edges iterator to return all regions (#53178).
1826
1857
if r == fr_static && self.constraint_graph.is_normal() {
1827
- for next_static_idx in self.constraint_graph.outgoing_edges_from_static() {
1828
- let constraint = OutlivesConstraint {
1829
- sup: fr_static,
1830
- sub: next_static_idx,
1831
- locations: Locations::All(DUMMY_SP),
1832
- span: DUMMY_SP,
1833
- category: ConstraintCategory::Internal,
1834
- variance_info: ty::VarianceDiagInfo::default(),
1835
- from_closure: false,
1836
- };
1837
- handle_constraint(&constraint);
1858
+ for sub in self.constraint_graph.outgoing_edges_from_static() {
1859
+ handle_trace(sub, Trace::FromStatic(sub));
1838
1860
}
1839
1861
} else {
1840
1862
let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints);
@@ -1844,25 +1866,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1844
1866
debug!("Ignoring illegal universe constraint: {constraint:?}");
1845
1867
continue;
1846
1868
}
1847
- handle_constraint(constraint);
1869
+ debug_assert_eq!(constraint.sup, r);
1870
+ handle_trace(constraint.sub, Trace::FromGraph(constraint));
1848
1871
}
1849
1872
}
1850
1873
1851
1874
// Member constraints can also give rise to `'r: 'x` edges that
1852
1875
// were not part of the graph initially, so watch out for those.
1853
1876
// (But they are extremely rare; this loop is very cold.)
1854
1877
for constraint in self.applied_member_constraints(self.constraint_sccs.scc(r)) {
1878
+ let sub = constraint.min_choice;
1855
1879
let p_c = &self.member_constraints[constraint.member_constraint_index];
1856
- let constraint = OutlivesConstraint {
1857
- sup: r,
1858
- sub: constraint.min_choice,
1859
- locations: Locations::All(p_c.definition_span),
1860
- span: p_c.definition_span,
1861
- category: ConstraintCategory::OpaqueType,
1862
- variance_info: ty::VarianceDiagInfo::default(),
1863
- from_closure: false,
1864
- };
1865
- handle_constraint(&constraint);
1880
+ handle_trace(sub, Trace::FromMember(r, sub, p_c.definition_span));
1866
1881
}
1867
1882
}
1868
1883
0 commit comments