@@ -3,7 +3,6 @@ use crate::infer::CombinedSnapshot;
33use rustc_data_structures:: {
44 fx:: FxIndexMap ,
55 graph:: { scc:: Sccs , vec_graph:: VecGraph } ,
6- undo_log:: UndoLogs ,
76} ;
87use rustc_index:: Idx ;
98use rustc_middle:: ty:: error:: TypeError ;
@@ -13,7 +12,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
1312 /// Searches new universes created during `snapshot`, looking for
1413 /// placeholders that may "leak" out from the universes they are contained
1514 /// in. If any leaking placeholders are found, then an `Err` is returned
16- /// (typically leading to the snapshot being reversed).
15+ /// (typically leading to the snapshot being reversed). This algorithm
16+ /// only looks at placeholders which cannot be named by `outer_universe`,
17+ /// as this is the universe we're currently checking for a leak.
1718 ///
1819 /// The leak check *used* to be the only way we had to handle higher-ranked
1920 /// obligations. Now that we have integrated universes into the region
@@ -55,36 +56,34 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
5556 /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that
5657 /// indicates `P: R` and `R` is in an incompatible universe
5758 ///
59+ /// To improve performance and for the old trait solver caching to be sound, this takes
60+ /// an optional snapshot in which case we only look at region constraints added in that
61+ /// snapshot. If we were to not do that the `leak_check` during evaluation can rely on
62+ /// region constraints added outside of that evaluation. As that is not reflected in the
63+ /// cache key this would be unsound.
64+ ///
5865 /// # Historical note
5966 ///
6067 /// Older variants of the leak check used to report errors for these
6168 /// patterns, but we no longer do:
6269 ///
6370 /// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n
6471 /// * R: P1, R: P2, as above
72+ #[ instrument( level = "debug" , skip( self , tcx, only_consider_snapshot) , ret) ]
6573 pub fn leak_check (
6674 & mut self ,
6775 tcx : TyCtxt < ' tcx > ,
76+ outer_universe : ty:: UniverseIndex ,
6877 max_universe : ty:: UniverseIndex ,
69- snapshot : & CombinedSnapshot < ' tcx > ,
78+ only_consider_snapshot : Option < & CombinedSnapshot < ' tcx > > ,
7079 ) -> RelateResult < ' tcx , ( ) > {
71- debug ! (
72- "leak_check(max_universe={:?}, snapshot.universe={:?})" ,
73- max_universe, snapshot. universe
74- ) ;
75-
76- assert ! ( UndoLogs :: <super :: UndoLog <' _>>:: in_snapshot( & self . undo_log) ) ;
77-
78- let universe_at_start_of_snapshot = snapshot. universe ;
79- if universe_at_start_of_snapshot == max_universe {
80+ if outer_universe == max_universe {
8081 return Ok ( ( ) ) ;
8182 }
8283
83- let mini_graph =
84- & MiniGraph :: new ( tcx, self . undo_log . region_constraints ( ) , & self . storage . data . verifys ) ;
84+ let mini_graph = & MiniGraph :: new ( tcx, & self , only_consider_snapshot) ;
8585
86- let mut leak_check =
87- LeakCheck :: new ( tcx, universe_at_start_of_snapshot, max_universe, mini_graph, self ) ;
86+ let mut leak_check = LeakCheck :: new ( tcx, outer_universe, max_universe, mini_graph, self ) ;
8887 leak_check. assign_placeholder_values ( ) ?;
8988 leak_check. propagate_scc_value ( ) ?;
9089 Ok ( ( ) )
@@ -93,7 +92,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
9392
9493struct LeakCheck < ' me , ' tcx > {
9594 tcx : TyCtxt < ' tcx > ,
96- universe_at_start_of_snapshot : ty:: UniverseIndex ,
95+ outer_universe : ty:: UniverseIndex ,
9796 mini_graph : & ' me MiniGraph < ' tcx > ,
9897 rcc : & ' me RegionConstraintCollector < ' me , ' tcx > ,
9998
@@ -121,15 +120,15 @@ struct LeakCheck<'me, 'tcx> {
121120impl < ' me , ' tcx > LeakCheck < ' me , ' tcx > {
122121 fn new (
123122 tcx : TyCtxt < ' tcx > ,
124- universe_at_start_of_snapshot : ty:: UniverseIndex ,
123+ outer_universe : ty:: UniverseIndex ,
125124 max_universe : ty:: UniverseIndex ,
126125 mini_graph : & ' me MiniGraph < ' tcx > ,
127126 rcc : & ' me RegionConstraintCollector < ' me , ' tcx > ,
128127 ) -> Self {
129128 let dummy_scc_universe = SccUniverse { universe : max_universe, region : None } ;
130129 Self {
131130 tcx,
132- universe_at_start_of_snapshot ,
131+ outer_universe ,
133132 mini_graph,
134133 rcc,
135134 scc_placeholders : IndexVec :: from_elem_n ( None , mini_graph. sccs . num_sccs ( ) ) ,
@@ -154,7 +153,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
154153
155154 // Detect those SCCs that directly contain a placeholder
156155 if let ty:: RePlaceholder ( placeholder) = * * region {
157- if self . universe_at_start_of_snapshot . cannot_name ( placeholder. universe ) {
156+ if self . outer_universe . cannot_name ( placeholder. universe ) {
158157 self . assign_scc_value ( scc, placeholder) ?;
159158 }
160159 }
@@ -364,56 +363,70 @@ struct MiniGraph<'tcx> {
364363}
365364
366365impl < ' tcx > MiniGraph < ' tcx > {
367- fn new < ' a > (
366+ fn new (
368367 tcx : TyCtxt < ' tcx > ,
369- undo_log : impl Iterator < Item = & ' a UndoLog < ' tcx > > ,
370- verifys : & [ Verify < ' tcx > ] ,
371- ) -> Self
372- where
373- ' tcx : ' a ,
374- {
368+ region_constraints : & RegionConstraintCollector < ' _ , ' tcx > ,
369+ only_consider_snapshot : Option < & CombinedSnapshot < ' tcx > > ,
370+ ) -> Self {
375371 let mut nodes = FxIndexMap :: default ( ) ;
376372 let mut edges = Vec :: new ( ) ;
377373
378374 // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter.
379- Self :: iterate_undo_log ( tcx, undo_log, verifys, |target, source| {
380- let source_node = Self :: add_node ( & mut nodes, source) ;
381- let target_node = Self :: add_node ( & mut nodes, target) ;
382- edges. push ( ( source_node, target_node) ) ;
383- } ) ;
375+ Self :: iterate_region_constraints (
376+ tcx,
377+ region_constraints,
378+ only_consider_snapshot,
379+ |target, source| {
380+ let source_node = Self :: add_node ( & mut nodes, source) ;
381+ let target_node = Self :: add_node ( & mut nodes, target) ;
382+ edges. push ( ( source_node, target_node) ) ;
383+ } ,
384+ ) ;
384385 let graph = VecGraph :: new ( nodes. len ( ) , edges) ;
385386 let sccs = Sccs :: new ( & graph) ;
386387 Self { nodes, sccs }
387388 }
388389
389390 /// Invokes `each_edge(R1, R2)` for each edge where `R2: R1`
390- fn iterate_undo_log < ' a > (
391+ fn iterate_region_constraints (
391392 tcx : TyCtxt < ' tcx > ,
392- undo_log : impl Iterator < Item = & ' a UndoLog < ' tcx > > ,
393- verifys : & [ Verify < ' tcx > ] ,
393+ region_constraints : & RegionConstraintCollector < ' _ , ' tcx > ,
394+ only_consider_snapshot : Option < & CombinedSnapshot < ' tcx > > ,
394395 mut each_edge : impl FnMut ( ty:: Region < ' tcx > , ty:: Region < ' tcx > ) ,
395- ) where
396- ' tcx : ' a ,
397- {
398- for undo_entry in undo_log {
399- match undo_entry {
400- & AddConstraint ( Constraint :: VarSubVar ( a, b) ) => {
401- each_edge ( ty:: Region :: new_var ( tcx, a) , ty:: Region :: new_var ( tcx, b) ) ;
402- }
403- & AddConstraint ( Constraint :: RegSubVar ( a, b) ) => {
404- each_edge ( a, ty:: Region :: new_var ( tcx, b) ) ;
405- }
406- & AddConstraint ( Constraint :: VarSubReg ( a, b) ) => {
407- each_edge ( ty:: Region :: new_var ( tcx, a) , b) ;
408- }
409- & AddConstraint ( Constraint :: RegSubReg ( a, b) ) => {
410- each_edge ( a, b) ;
396+ ) {
397+ let mut each_constraint = |constraint| match constraint {
398+ & Constraint :: VarSubVar ( a, b) => {
399+ each_edge ( ty:: Region :: new_var ( tcx, a) , ty:: Region :: new_var ( tcx, b) ) ;
400+ }
401+ & Constraint :: RegSubVar ( a, b) => {
402+ each_edge ( a, ty:: Region :: new_var ( tcx, b) ) ;
403+ }
404+ & Constraint :: VarSubReg ( a, b) => {
405+ each_edge ( ty:: Region :: new_var ( tcx, a) , b) ;
406+ }
407+ & Constraint :: RegSubReg ( a, b) => {
408+ each_edge ( a, b) ;
409+ }
410+ } ;
411+
412+ if let Some ( snapshot) = only_consider_snapshot {
413+ for undo_entry in
414+ region_constraints. undo_log . region_constraints_in_snapshot ( & snapshot. undo_snapshot )
415+ {
416+ match undo_entry {
417+ AddConstraint ( constraint) => {
418+ each_constraint ( constraint) ;
419+ }
420+ & AddVerify ( i) => span_bug ! (
421+ region_constraints. data( ) . verifys[ i] . origin. span( ) ,
422+ "we never add verifications while doing higher-ranked things" ,
423+ ) ,
424+ & AddCombination ( ..) | & AddVar ( ..) => { }
411425 }
412- & AddVerify ( i) => span_bug ! (
413- verifys[ i] . origin. span( ) ,
414- "we never add verifications while doing higher-ranked things" ,
415- ) ,
416- & AddCombination ( ..) | & AddVar ( ..) => { }
426+ }
427+ } else {
428+ for ( constraint, _origin) in & region_constraints. data ( ) . constraints {
429+ each_constraint ( constraint)
417430 }
418431 }
419432 }
0 commit comments