@@ -3,7 +3,6 @@ use crate::infer::CombinedSnapshot;
3
3
use rustc_data_structures:: {
4
4
fx:: FxIndexMap ,
5
5
graph:: { scc:: Sccs , vec_graph:: VecGraph } ,
6
- undo_log:: UndoLogs ,
7
6
} ;
8
7
use rustc_index:: Idx ;
9
8
use rustc_middle:: ty:: error:: TypeError ;
@@ -13,7 +12,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
13
12
/// Searches new universes created during `snapshot`, looking for
14
13
/// placeholders that may "leak" out from the universes they are contained
15
14
/// 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.
17
18
///
18
19
/// The leak check *used* to be the only way we had to handle higher-ranked
19
20
/// obligations. Now that we have integrated universes into the region
@@ -55,36 +56,34 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
55
56
/// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that
56
57
/// indicates `P: R` and `R` is in an incompatible universe
57
58
///
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
+ ///
58
65
/// # Historical note
59
66
///
60
67
/// Older variants of the leak check used to report errors for these
61
68
/// patterns, but we no longer do:
62
69
///
63
70
/// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n
64
71
/// * R: P1, R: P2, as above
72
+ #[ instrument( level = "debug" , skip( self , tcx, only_consider_snapshot) , ret) ]
65
73
pub fn leak_check (
66
74
& mut self ,
67
75
tcx : TyCtxt < ' tcx > ,
76
+ outer_universe : ty:: UniverseIndex ,
68
77
max_universe : ty:: UniverseIndex ,
69
- snapshot : & CombinedSnapshot < ' tcx > ,
78
+ only_consider_snapshot : Option < & CombinedSnapshot < ' tcx > > ,
70
79
) -> 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 {
80
81
return Ok ( ( ) ) ;
81
82
}
82
83
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) ;
85
85
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 ) ;
88
87
leak_check. assign_placeholder_values ( ) ?;
89
88
leak_check. propagate_scc_value ( ) ?;
90
89
Ok ( ( ) )
@@ -93,7 +92,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
93
92
94
93
struct LeakCheck < ' me , ' tcx > {
95
94
tcx : TyCtxt < ' tcx > ,
96
- universe_at_start_of_snapshot : ty:: UniverseIndex ,
95
+ outer_universe : ty:: UniverseIndex ,
97
96
mini_graph : & ' me MiniGraph < ' tcx > ,
98
97
rcc : & ' me RegionConstraintCollector < ' me , ' tcx > ,
99
98
@@ -121,15 +120,15 @@ struct LeakCheck<'me, 'tcx> {
121
120
impl < ' me , ' tcx > LeakCheck < ' me , ' tcx > {
122
121
fn new (
123
122
tcx : TyCtxt < ' tcx > ,
124
- universe_at_start_of_snapshot : ty:: UniverseIndex ,
123
+ outer_universe : ty:: UniverseIndex ,
125
124
max_universe : ty:: UniverseIndex ,
126
125
mini_graph : & ' me MiniGraph < ' tcx > ,
127
126
rcc : & ' me RegionConstraintCollector < ' me , ' tcx > ,
128
127
) -> Self {
129
128
let dummy_scc_universe = SccUniverse { universe : max_universe, region : None } ;
130
129
Self {
131
130
tcx,
132
- universe_at_start_of_snapshot ,
131
+ outer_universe ,
133
132
mini_graph,
134
133
rcc,
135
134
scc_placeholders : IndexVec :: from_elem_n ( None , mini_graph. sccs . num_sccs ( ) ) ,
@@ -154,7 +153,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
154
153
155
154
// Detect those SCCs that directly contain a placeholder
156
155
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 ) {
158
157
self . assign_scc_value ( scc, placeholder) ?;
159
158
}
160
159
}
@@ -364,56 +363,70 @@ struct MiniGraph<'tcx> {
364
363
}
365
364
366
365
impl < ' tcx > MiniGraph < ' tcx > {
367
- fn new < ' a > (
366
+ fn new (
368
367
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 {
375
371
let mut nodes = FxIndexMap :: default ( ) ;
376
372
let mut edges = Vec :: new ( ) ;
377
373
378
374
// 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
+ ) ;
384
385
let graph = VecGraph :: new ( nodes. len ( ) , edges) ;
385
386
let sccs = Sccs :: new ( & graph) ;
386
387
Self { nodes, sccs }
387
388
}
388
389
389
390
/// Invokes `each_edge(R1, R2)` for each edge where `R2: R1`
390
- fn iterate_undo_log < ' a > (
391
+ fn iterate_region_constraints (
391
392
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 > > ,
394
395
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 ( ..) => { }
411
425
}
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)
417
430
}
418
431
}
419
432
}
0 commit comments