diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index f03e8bd7ac1..9a3076c0c32 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -872,35 +872,50 @@ impl<'tcx> RegionInferenceContext<'tcx> { // be obvious to the user -- not to mention the naive notion // of dependencies, which doesn't account for the locations of // contraints at all. But it will do for now. - for constraint in &self.constraints { - if constraint.sub == fr2 && influenced_fr1[constraint.sup] { - return constraint.span; - } - } + let relevant_constraint = self.constraints + .iter() + .filter_map(|constraint| { + if constraint.sub != fr2 { + None + } else { + influenced_fr1[constraint.sup] + .map(|distance| (distance, constraint.span)) + } + }) + .min() // constraining fr1 with fewer hops *ought* to be more obvious + .map(|(_dist, span)| span); - bug!( - "could not find any constraint to blame for {:?}: {:?}", - fr1, - fr2 - ); + relevant_constraint.unwrap_or_else(|| { + bug!( + "could not find any constraint to blame for {:?}: {:?}", + fr1, + fr2 + ); + }) } /// Finds all regions whose values `'a` may depend on in some way. - /// Basically if there exists a constraint `'a: 'b @ P`, then `'b` - /// and `dependencies('b)` will be in the final set. + /// For each region, returns either `None` (does not influence + /// `'a`) or `Some(d)` which indicates that it influences `'a` + /// with distinct `d` (minimum number of edges that must be + /// traversed). /// /// Used during error reporting, extremely naive and inefficient. - fn dependencies(&self, r0: RegionVid) -> IndexVec { - let mut result_set = IndexVec::from_elem(false, &self.definitions); + fn dependencies(&self, r0: RegionVid) -> IndexVec> { + let mut result_set = IndexVec::from_elem(None, &self.definitions); let mut changed = true; - result_set[r0] = true; + result_set[r0] = Some(0); // distance 0 from `r0` while changed { changed = false; for constraint in &self.constraints { - if result_set[constraint.sup] { - if !result_set[constraint.sub] { - result_set[constraint.sub] = true; + if let Some(n) = result_set[constraint.sup] { + let m = n + 1; + if result_set[constraint.sub] + .map(|distance| m < distance) + .unwrap_or(true) + { + result_set[constraint.sub] = Some(m); changed = true; } } @@ -1049,13 +1064,16 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi value: &T, ) -> T where - T: TypeFoldable<'tcx> + T: TypeFoldable<'tcx>, { infcx.tcx.fold_regions(value, &mut false, |r, _depth| { if let ty::ReClosureBound(vid) = r { closure_mapping[*vid] } else { - bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r) + bug!( + "subst_closure_mapping: encountered non-closure bound free region {:?}", + r + ) } }) } diff --git a/src/test/compile-fail/mir_check_cast_closure.rs b/src/test/compile-fail/mir_check_cast_closure.rs index be0d4b13741..6562efeb6d8 100644 --- a/src/test/compile-fail/mir_check_cast_closure.rs +++ b/src/test/compile-fail/mir_check_cast_closure.rs @@ -14,9 +14,9 @@ fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 { let g: fn(_, _) -> _ = |_x, y| y; + //~^ ERROR free region `'b` does not outlive free region `'a` g //~^ WARNING not reporting region error due to -Znll - //~| ERROR free region `'b` does not outlive free region `'a` } fn main() {} diff --git a/src/test/compile-fail/mir_check_cast_reify.rs b/src/test/compile-fail/mir_check_cast_reify.rs index 091e0b71b2d..1736aea2d6d 100644 --- a/src/test/compile-fail/mir_check_cast_reify.rs +++ b/src/test/compile-fail/mir_check_cast_reify.rs @@ -45,8 +45,8 @@ fn bar<'a>(x: &'a u32) -> &'static u32 { // as part of checking the `ReifyFnPointer`. let f: fn(_) -> _ = foo; //~^ WARNING not reporting region error due to -Znll + //~| ERROR free region `'_#1r` does not outlive free region `'static` f(x) - //~^ ERROR free region `'_#1r` does not outlive free region `'static` } fn main() {} diff --git a/src/test/compile-fail/mir_check_cast_unsafe_fn.rs b/src/test/compile-fail/mir_check_cast_unsafe_fn.rs index 701a7c6b056..39eafa10040 100644 --- a/src/test/compile-fail/mir_check_cast_unsafe_fn.rs +++ b/src/test/compile-fail/mir_check_cast_unsafe_fn.rs @@ -17,8 +17,8 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { // in `g`. These are related via the `UnsafeFnPointer` cast. let g: unsafe fn(_) -> _ = f; //~^ WARNING not reporting region error due to -Znll + //~| ERROR free region `'_#1r` does not outlive free region `'static` unsafe { g(input) } - //~^ ERROR free region `'_#1r` does not outlive free region `'static` } fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs index c2f071cc029..50d7877de50 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs @@ -54,8 +54,8 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell // Only works if 'x: 'y: let p = x.get(); //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#5r` does not outlive free region `'_#6r` demand_y(x, y, p) - //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r` }, ); } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index cdda8ab5392..f90bc7c175a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -5,10 +5,10 @@ warning: not reporting region error due to -Znll | ^^^^^^^ error: free region `'_#5r` does not outlive free region `'_#6r` - --> $DIR/propagate-approximated-fail-no-postdom.rs:57:25 + --> $DIR/propagate-approximated-fail-no-postdom.rs:55:17 | -57 | demand_y(x, y, p) - | ^ +55 | let p = x.get(); + | ^ note: No external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9 @@ -17,8 +17,8 @@ note: No external requirements 54 | | // Only works if 'x: 'y: 55 | | let p = x.get(); 56 | | //~^ WARN not reporting region error due to -Znll -57 | | demand_y(x, y, p) -58 | | //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r` +57 | | //~| ERROR free region `'_#5r` does not outlive free region `'_#6r` +58 | | demand_y(x, y, p) 59 | | }, | |_________^ | diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 717cf481a01..4bae29ad326 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -24,10 +24,10 @@ note: External requirements = note: where '_#1r: '_#2r error: free region `'_#1r` does not outlive free region `'_#2r` - --> $DIR/propagate-approximated-ref.rs:53:38 + --> $DIR/propagate-approximated-ref.rs:53:29 | 53 | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | ^^^^^^^ + | ^^^^^^^ note: No external requirements --> $DIR/propagate-approximated-ref.rs:52:1 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr index e8dc8a13f87..502b344c89e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr @@ -5,10 +5,10 @@ warning: not reporting region error due to -Znll | ^^^^^^^^^^^^^^^^^^^^^^^ error: free region `'_#6r` does not outlive free region `'_#4r` - --> $DIR/propagate-approximated-to-empty.rs:41:21 + --> $DIR/propagate-approximated-to-empty.rs:41:18 | 41 | demand_y(x, y, x.get()) - | ^ + | ^ note: No external requirements --> $DIR/propagate-approximated-to-empty.rs:39:47 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 43464bfb2b9..43d61fdf1b5 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -24,10 +24,10 @@ note: External requirements = note: where '_#1r: '_#2r error: free region `'_#1r` does not outlive free region `'_#2r` - --> $DIR/propagate-approximated-val.rs:46:37 + --> $DIR/propagate-approximated-val.rs:46:29 | 46 | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { - | ^^^^^^ + | ^^^^^^ note: No external requirements --> $DIR/propagate-approximated-val.rs:45:1 diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs index d5bd4b60118..a5be2b43f04 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs @@ -40,6 +40,8 @@ where T: Trait<'a>, { establish_relationships(value, |value| { + //~^ ERROR failed type test + // This function call requires that // // (a) T: Trait<'a> @@ -52,7 +54,6 @@ where require(value); //~^ WARNING not reporting region error due to -Znll - //~| ERROR failed type test }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index eb415ec8d1a..e81c45ef7ed 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -1,7 +1,7 @@ warning: not reporting region error due to -Znll - --> $DIR/propagate-from-trait-match.rs:53:9 + --> $DIR/propagate-from-trait-match.rs:55:9 | -53 | require(value); +55 | require(value); | ^^^^^^^ note: External requirements @@ -9,12 +9,12 @@ note: External requirements | 42 | establish_relationships(value, |value| { | ____________________________________^ -43 | | // This function call requires that -44 | | // -45 | | // (a) T: Trait<'a> +43 | | //~^ ERROR failed type test +44 | | +45 | | // This function call requires that ... | -55 | | //~| ERROR failed type test -56 | | }); +56 | | //~^ WARNING not reporting region error due to -Znll +57 | | }); | |_____^ | = note: defining type: DefId(0/1:16 ~ propagate_from_trait_match[317d]::supply[0]::{{closure}}[0]) with closure substs [ @@ -26,17 +26,17 @@ note: External requirements = note: number of external vids: 2 = note: where T: '_#1r -error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#3r, point: bb0[3], span: $DIR/propagate-from-trait-match.rs:42:36: 56:6, test: IsOutlivedByAnyRegionIn(['_#2r]) } +error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#3r, point: bb0[3], span: $DIR/propagate-from-trait-match.rs:42:36: 57:6, test: IsOutlivedByAnyRegionIn(['_#2r]) } --> $DIR/propagate-from-trait-match.rs:42:36 | 42 | establish_relationships(value, |value| { | ____________________________________^ -43 | | // This function call requires that -44 | | // -45 | | // (a) T: Trait<'a> +43 | | //~^ ERROR failed type test +44 | | +45 | | // This function call requires that ... | -55 | | //~| ERROR failed type test -56 | | }); +56 | | //~^ WARNING not reporting region error due to -Znll +57 | | }); | |_____^ note: No external requirements @@ -47,8 +47,8 @@ note: No external requirements 40 | | T: Trait<'a>, 41 | | { ... | -56 | | }); -57 | | } +57 | | }); +58 | | } | |_^ | = note: defining type: DefId(0/0:6 ~ propagate_from_trait_match[317d]::supply[0]) with substs [