@@ -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