8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use borrow_check:: nll:: region_infer:: values:: ToElementIndex ;
12
11
use borrow_check:: nll:: region_infer:: { ConstraintIndex , RegionInferenceContext } ;
13
12
use borrow_check:: nll:: type_check:: Locations ;
14
13
use rustc:: hir:: def_id:: DefId ;
@@ -75,11 +74,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
75
74
mir : & Mir < ' tcx > ,
76
75
from_region : RegionVid ,
77
76
target_test : impl Fn ( RegionVid ) -> bool ,
78
- ) -> ( ConstraintCategory , Span ) {
77
+ ) -> ( ConstraintCategory , Span , RegionVid ) {
79
78
debug ! ( "best_blame_constraint(from_region={:?})" , from_region) ;
80
79
81
80
// Find all paths
82
- let path = self
81
+ let ( path, target_region ) = self
83
82
. find_constraint_paths_between_regions ( from_region, target_test)
84
83
. unwrap ( ) ;
85
84
debug ! ( "best_blame_constraint: path={:#?}" , path) ;
@@ -98,19 +97,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
98
97
categorized_path. sort_by ( |p0, p1| p0. 0 . cmp ( & p1. 0 ) ) ;
99
98
debug ! ( "best_blame_constraint: sorted_path={:?}" , categorized_path) ;
100
99
101
- * categorized_path. first ( ) . unwrap ( )
100
+ let & ( category, span) = categorized_path. first ( ) . unwrap ( ) ;
101
+
102
+ ( category, span, target_region)
102
103
}
103
104
104
105
/// Walks the graph of constraints (where `'a: 'b` is considered
105
106
/// an edge `'a -> 'b`) to find all paths from `from_region` to
106
107
/// `to_region`. The paths are accumulated into the vector
107
108
/// `results`. The paths are stored as a series of
108
109
/// `ConstraintIndex` values -- in other words, a list of *edges*.
110
+ ///
111
+ /// Returns: a series of constraints as well as the region `R`
112
+ /// that passed the target test.
109
113
fn find_constraint_paths_between_regions (
110
114
& self ,
111
115
from_region : RegionVid ,
112
116
target_test : impl Fn ( RegionVid ) -> bool ,
113
- ) -> Option < Vec < ConstraintIndex > > {
117
+ ) -> Option < ( Vec < ConstraintIndex > , RegionVid ) > {
114
118
let mut context = IndexVec :: from_elem ( Trace :: NotVisited , & self . definitions ) ;
115
119
context[ from_region] = Trace :: StartRegion ;
116
120
@@ -138,7 +142,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
138
142
139
143
Trace :: StartRegion => {
140
144
result. reverse ( ) ;
141
- return Some ( result) ;
145
+ return Some ( ( result, r ) ) ;
142
146
}
143
147
}
144
148
}
@@ -253,7 +257,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
253
257
) {
254
258
debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
255
259
256
- let ( category, span) = self . best_blame_constraint ( mir, fr, |r| r == outlived_fr) ;
260
+ let ( category, span, _ ) = self . best_blame_constraint ( mir, fr, |r| r == outlived_fr) ;
257
261
258
262
// Check if we can use one of the "nice region errors".
259
263
if let ( Some ( f) , Some ( o) ) = ( self . to_error_region ( fr) , self . to_error_region ( outlived_fr) ) {
@@ -393,82 +397,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
393
397
diag. buffer ( errors_buffer) ;
394
398
}
395
399
396
- // Find some constraint `X: Y` where:
397
- // - `fr1: X` transitively
398
- // - and `Y` is live at `elem`
399
- crate fn find_constraint ( & self , fr1 : RegionVid , elem : Location ) -> RegionVid {
400
- let index = self . blame_constraint ( fr1, elem) ;
401
- self . constraints [ index] . sub
402
- }
403
-
404
- /// Tries to finds a good span to blame for the fact that `fr1`
405
- /// contains `fr2`.
406
- pub ( super ) fn blame_constraint (
407
- & self ,
408
- fr1 : RegionVid ,
409
- elem : impl ToElementIndex ,
410
- ) -> ConstraintIndex {
411
- // Find everything that influenced final value of `fr`.
412
- let influenced_fr1 = self . dependencies ( fr1) ;
413
-
414
- // Try to find some outlives constraint `'X: fr2` where `'X`
415
- // influenced `fr1`. Blame that.
416
- //
417
- // NB, this is a pretty bad choice most of the time. In
418
- // particular, the connection between `'X` and `fr1` may not
419
- // be obvious to the user -- not to mention the naive notion
420
- // of dependencies, which doesn't account for the locations of
421
- // contraints at all. But it will do for now.
422
- let relevant_constraint = self . constraints
423
- . iter_enumerated ( )
424
- . filter_map ( |( i, constraint) | {
425
- if !self . liveness_constraints . contains ( constraint. sub , elem) {
426
- None
427
- } else {
428
- influenced_fr1[ constraint. sup ]
429
- . map ( |distance| ( distance, i) )
430
- }
400
+ // Finds some region R such that `fr1: R` and `R` is live at
401
+ // `elem`.
402
+ crate fn find_sub_region_live_at ( & self , fr1 : RegionVid , elem : Location ) -> RegionVid {
403
+ // Find all paths
404
+ let ( _path, r) = self
405
+ . find_constraint_paths_between_regions ( fr1, |r| {
406
+ self . liveness_constraints . contains ( r, elem)
431
407
} )
432
- . min ( ) // constraining fr1 with fewer hops *ought* to be more obvious
433
- . map ( |( _dist, i) | i) ;
434
-
435
- relevant_constraint. unwrap_or_else ( || {
436
- bug ! (
437
- "could not find any constraint to blame for {:?}: {:?}" ,
438
- fr1,
439
- elem,
440
- ) ;
441
- } )
408
+ . unwrap ( ) ;
409
+ r
442
410
}
443
411
444
- /// Finds all regions whose values `'a` may depend on in some way.
445
- /// For each region, returns either `None` (does not influence
446
- /// `'a`) or `Some(d)` which indicates that it influences `'a`
447
- /// with distinct `d` (minimum number of edges that must be
448
- /// traversed).
449
- ///
450
- /// Used during error reporting, extremely naive and inefficient.
451
- fn dependencies ( & self , r0 : RegionVid ) -> IndexVec < RegionVid , Option < usize > > {
452
- let mut result_set = IndexVec :: from_elem ( None , & self . definitions ) ;
453
- let mut changed = true ;
454
- result_set[ r0] = Some ( 0 ) ; // distance 0 from `r0`
455
-
456
- while changed {
457
- changed = false ;
458
- for constraint in self . constraints . iter ( ) {
459
- if let Some ( n) = result_set[ constraint. sup ] {
460
- let m = n + 1 ;
461
- if result_set[ constraint. sub ]
462
- . map ( |distance| m < distance)
463
- . unwrap_or ( true )
464
- {
465
- result_set[ constraint. sub ] = Some ( m) ;
466
- changed = true ;
467
- }
468
- }
469
- }
470
- }
471
-
472
- result_set
412
+ // Finds a good span to blame for the fact that `fr1` outlives `fr2`.
413
+ crate fn find_outlives_blame_span ( & self , mir : & Mir < ' tcx > , fr1 : RegionVid , fr2 : RegionVid ) -> Span {
414
+ let ( _, span, _) = self . best_blame_constraint ( mir, fr1, |r| r == fr2) ;
415
+ span
473
416
}
474
417
}
0 commit comments