88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use borrow_check:: nll:: region_infer:: values:: ToElementIndex ;
1211use borrow_check:: nll:: region_infer:: { ConstraintIndex , RegionInferenceContext } ;
1312use borrow_check:: nll:: type_check:: Locations ;
1413use rustc:: hir:: def_id:: DefId ;
@@ -75,11 +74,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
7574 mir : & Mir < ' tcx > ,
7675 from_region : RegionVid ,
7776 target_test : impl Fn ( RegionVid ) -> bool ,
78- ) -> ( ConstraintCategory , Span ) {
77+ ) -> ( ConstraintCategory , Span , RegionVid ) {
7978 debug ! ( "best_blame_constraint(from_region={:?})" , from_region) ;
8079
8180 // Find all paths
82- let path = self
81+ let ( path, target_region ) = self
8382 . find_constraint_paths_between_regions ( from_region, target_test)
8483 . unwrap ( ) ;
8584 debug ! ( "best_blame_constraint: path={:#?}" , path) ;
@@ -98,19 +97,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9897 categorized_path. sort_by ( |p0, p1| p0. 0 . cmp ( & p1. 0 ) ) ;
9998 debug ! ( "best_blame_constraint: sorted_path={:?}" , categorized_path) ;
10099
101- * categorized_path. first ( ) . unwrap ( )
100+ let & ( category, span) = categorized_path. first ( ) . unwrap ( ) ;
101+
102+ ( category, span, target_region)
102103 }
103104
104105 /// Walks the graph of constraints (where `'a: 'b` is considered
105106 /// an edge `'a -> 'b`) to find all paths from `from_region` to
106107 /// `to_region`. The paths are accumulated into the vector
107108 /// `results`. The paths are stored as a series of
108109 /// `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.
109113 fn find_constraint_paths_between_regions (
110114 & self ,
111115 from_region : RegionVid ,
112116 target_test : impl Fn ( RegionVid ) -> bool ,
113- ) -> Option < Vec < ConstraintIndex > > {
117+ ) -> Option < ( Vec < ConstraintIndex > , RegionVid ) > {
114118 let mut context = IndexVec :: from_elem ( Trace :: NotVisited , & self . definitions ) ;
115119 context[ from_region] = Trace :: StartRegion ;
116120
@@ -138,7 +142,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
138142
139143 Trace :: StartRegion => {
140144 result. reverse ( ) ;
141- return Some ( result) ;
145+ return Some ( ( result, r ) ) ;
142146 }
143147 }
144148 }
@@ -253,7 +257,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
253257 ) {
254258 debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
255259
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) ;
257261
258262 // Check if we can use one of the "nice region errors".
259263 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> {
393397 diag. buffer ( errors_buffer) ;
394398 }
395399
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)
431407 } )
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
442410 }
443411
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
473416 }
474417}
0 commit comments