diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2018-08-05 14:33:38 +0100 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2018-08-05 14:33:38 +0100 |
| commit | f72b8a44c51313d384deefcda753df668f2e265e (patch) | |
| tree | 614c7ac810f1a856109e586a1d713f22f193e088 /src | |
| parent | ddcf17e1ed577bad26e92db3c25499620f853a49 (diff) | |
| download | rust-f72b8a44c51313d384deefcda753df668f2e265e.tar.gz rust-f72b8a44c51313d384deefcda753df668f2e265e.zip | |
Use span of the closure args in free region errors
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs | 62 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr | 5 | ||||
| -rw-r--r-- | src/test/ui/issue-40510-1.nll.stderr | 20 | ||||
| -rw-r--r-- | src/test/ui/issue-40510-3.nll.stderr | 25 | ||||
| -rw-r--r-- | src/test/ui/issue-49824.nll.stderr | 25 | ||||
| -rw-r--r-- | src/test/ui/nll/issue-48238.stderr | 9 |
6 files changed, 91 insertions, 55 deletions
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 79165276430..6a21e002588 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -10,6 +10,7 @@ use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; +use borrow_check::nll::universal_regions::DefiningTy; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; @@ -72,7 +73,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_output( - infcx.tcx, mir, fr, counter, diag) + infcx.tcx, mir, mir_def_id, fr, counter, diag) }) .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr)) } @@ -107,13 +108,46 @@ impl<'tcx> RegionInferenceContext<'tcx> { }, ty::BoundRegion::BrEnv => { - let closure_span = tcx.hir.span_if_local(mir_def_id).unwrap(); - let region_name = self.synthesize_region_name(counter); - diag.span_label( - closure_span, - format!("lifetime `{}` represents the closure body", region_name), - ); - Some(region_name) + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); + let def_ty = self.universal_regions.defining_ty; + + if let DefiningTy::Closure(def_id, substs) = def_ty { + let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) + = tcx.hir.expect_expr(mir_node_id).node + { + span + } else { + bug!("Closure is not defined by a closure expr"); + }; + let region_name = self.synthesize_region_name(counter); + diag.span_label( + args_span, + format!("lifetime `{}` represents this closure's body", region_name), + ); + + let closure_kind_ty = substs.closure_kind_ty(def_id, tcx); + let note = match closure_kind_ty.to_opt_closure_kind() { + Some(ty::ClosureKind::Fn) => { + "closure implements `Fn`, so references to captured variables \ + can't escape the closure" + } + Some(ty::ClosureKind::FnMut) => { + "closure implements `FnMut`, so references to captured variables \ + can't escape the closure" + } + Some(ty::ClosureKind::FnOnce) => { + bug!("BrEnv in a `FnOnce` closure"); + } + None => bug!("Closure kind not inferred in borrow check"), + }; + + diag.note(note); + + Some(region_name) + } else { + // Can't have BrEnv in functions, constants or generators. + bug!("BrEnv outside of closure."); + } } ty::BoundRegion::BrAnon(_) | ty::BoundRegion::BrFresh(_) => None, @@ -545,6 +579,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>, + mir_def_id: DefId, fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, @@ -558,9 +593,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { return None; } + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); + let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) + = tcx.hir.expect_expr(mir_node_id).node + { + span + } else { + mir.span + }; + let region_name = self.synthesize_region_name(counter); diag.span_label( - mir.span, + args_span, format!("lifetime `{}` appears in return type", region_name), ); diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr index 0ac295c54bc..27a51cb83fb 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr @@ -8,9 +8,8 @@ error: unsatisfied lifetime constraints --> $DIR/E0621-does-not-trigger-for-closures.rs:25:26 | LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 - | ----------^^^^^----------------- - | | | | - | | | requires that `'1` must outlive `'2` + | ------ ^^^^^ requires that `'1` must outlive `'2` + | | | | | has type `&'1 i32` | lifetime `'2` appears in return type diff --git a/src/test/ui/issue-40510-1.nll.stderr b/src/test/ui/issue-40510-1.nll.stderr index 312ec6e742e..7eb6a0e7fb2 100644 --- a/src/test/ui/issue-40510-1.nll.stderr +++ b/src/test/ui/issue-40510-1.nll.stderr @@ -1,17 +1,15 @@ error: unsatisfied lifetime constraints --> $DIR/issue-40510-1.rs:18:9 | -LL | || { - | _____- - | |_____| - | || -LL | || &mut x - | || ^^^^^^ return requires that `'1` must outlive `'2` -LL | || }; - | || - - | ||_____| - | |______lifetime `'1` represents the closure body - | lifetime `'2` appears in return type +LL | || { + | -- + | | + | lifetime `'1` represents this closure's body + | lifetime `'2` appears in return type +LL | &mut x + | ^^^^^^ return requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure error: aborting due to previous error diff --git a/src/test/ui/issue-40510-3.nll.stderr b/src/test/ui/issue-40510-3.nll.stderr index eb44850e639..ae3ae3a27ab 100644 --- a/src/test/ui/issue-40510-3.nll.stderr +++ b/src/test/ui/issue-40510-3.nll.stderr @@ -1,20 +1,17 @@ error: unsatisfied lifetime constraints --> $DIR/issue-40510-3.rs:18:9 | -LL | || { - | _____- - | |_____| - | || -LL | || || { - | ||_________^ -LL | ||| x.push(()) -LL | ||| } - | |||_________^ requires that `'1` must outlive `'2` -LL | || }; - | || - - | ||_____| - | |______lifetime `'1` represents the closure body - | lifetime `'2` appears in return type +LL | || { + | -- + | | + | lifetime `'1` represents this closure's body + | lifetime `'2` appears in return type +LL | / || { +LL | | x.push(()) +LL | | } + | |_________^ requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure error: aborting due to previous error diff --git a/src/test/ui/issue-49824.nll.stderr b/src/test/ui/issue-49824.nll.stderr index 59345754e9f..432036c9d90 100644 --- a/src/test/ui/issue-49824.nll.stderr +++ b/src/test/ui/issue-49824.nll.stderr @@ -1,20 +1,17 @@ error: unsatisfied lifetime constraints --> $DIR/issue-49824.rs:22:9 | -LL | || { - | _____- - | |_____| - | || -LL | || || { - | ||_________^ -LL | ||| let _y = &mut x; -LL | ||| } - | |||_________^ requires that `'1` must outlive `'2` -LL | || }; - | || - - | ||_____| - | |______lifetime `'1` represents the closure body - | lifetime `'2` appears in return type +LL | || { + | -- + | | + | lifetime `'1` represents this closure's body + | lifetime `'2` appears in return type +LL | / || { +LL | | let _y = &mut x; +LL | | } + | |_________^ requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure error: aborting due to previous error diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr index 7bdac345e90..4baa9044424 100644 --- a/src/test/ui/nll/issue-48238.stderr +++ b/src/test/ui/nll/issue-48238.stderr @@ -2,11 +2,12 @@ error: unsatisfied lifetime constraints --> $DIR/issue-48238.rs:21:13 | LL | move || use_val(&orig); //~ ERROR - | --------^^^^^^^^^^^^^^ - | | | - | | argument requires that `'1` must outlive `'2` - | lifetime `'1` represents the closure body + | ------- ^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | + | lifetime `'1` represents this closure's body | lifetime `'2` appears in return type + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure error: aborting due to previous error |
