@@ -311,9 +311,11 @@ enum RegionRelationCheckResult {
311311}
312312
313313#[ derive( Clone , PartialEq , Eq , Debug ) ]
314- enum Trace < ' tcx > {
314+ enum Trace < ' a , ' tcx > {
315315 StartRegion ,
316- FromOutlivesConstraint ( OutlivesConstraint < ' tcx > ) ,
316+ FromGraph ( & ' a OutlivesConstraint < ' tcx > ) ,
317+ FromStatic ( RegionVid ) ,
318+ FromMember ( RegionVid , RegionVid , Span ) ,
317319 NotVisited ,
318320}
319321
@@ -1764,6 +1766,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17641766 let mut context = IndexVec :: from_elem ( Trace :: NotVisited , & self . definitions ) ;
17651767 context[ from_region] = Trace :: StartRegion ;
17661768
1769+ let fr_static = self . universal_regions ( ) . fr_static ;
1770+
17671771 // Use a deque so that we do a breadth-first search. We will
17681772 // stop at the first match, which ought to be the shortest
17691773 // path (fewest constraints).
@@ -1783,13 +1787,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17831787 if target_test ( r) {
17841788 let mut result = vec ! [ ] ;
17851789 let mut p = r;
1790+ // This loop is cold and runs at the end, which is why we delay
1791+ // `OutlivesConstraint` construction until now.
17861792 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) ;
17901797 }
17911798
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+ } ;
17931823 p = c. sup ;
17941824 result. push ( c) ;
17951825 }
@@ -1798,6 +1828,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17981828 result. reverse ( ) ;
17991829 return Some ( ( result, r) ) ;
18001830 }
1831+
1832+ Trace :: NotVisited => {
1833+ bug ! ( "found unvisited region {:?} on path to {:?}" , p, r)
1834+ }
18011835 }
18021836 }
18031837 }
@@ -1808,33 +1842,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
18081842
18091843 // A constraint like `'r: 'x` can come from our constraint
18101844 // graph.
1811- let fr_static = self . universal_regions ( ) . fr_static ;
18121845
18131846 // 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) ;
18211852 }
18221853 } ;
18231854
18241855 // If this is the `'static` region and the graph's direction is normal, then set up the
18251856 // Edges iterator to return all regions (#53178).
18261857 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) ) ;
18381860 }
18391861 } else {
18401862 let edges = self . constraint_graph . outgoing_edges_from_graph ( r, & self . constraints ) ;
@@ -1844,25 +1866,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
18441866 debug ! ( "Ignoring illegal universe constraint: {constraint:?}" ) ;
18451867 continue ;
18461868 }
1847- handle_constraint ( constraint) ;
1869+ debug_assert_eq ! ( constraint. sup, r) ;
1870+ handle_trace ( constraint. sub , Trace :: FromGraph ( constraint) ) ;
18481871 }
18491872 }
18501873
18511874 // Member constraints can also give rise to `'r: 'x` edges that
18521875 // were not part of the graph initially, so watch out for those.
18531876 // (But they are extremely rare; this loop is very cold.)
18541877 for constraint in self . applied_member_constraints ( self . constraint_sccs . scc ( r) ) {
1878+ let sub = constraint. min_choice ;
18551879 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 ) ) ;
18661881 }
18671882 }
18681883
0 commit comments