From 2488cb6b1027bf88e33dfdc7ce89472f5dc54714 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 2 Aug 2018 12:00:15 +0200 Subject: [PATCH] Explicitly label any named lifetimes mentioned in error messages. --- .../error_reporting/region_name.rs | 54 +++++++++++++++++-- .../static-return-lifetime-infered.nll.stderr | 2 + src/test/ui/issue-10291.nll.stderr | 2 + src/test/ui/issue-52213.nll.stderr | 5 ++ ...n-lbr-named-does-not-outlive-static.stderr | 2 + src/test/ui/nll/mir_check_cast_closure.stderr | 4 ++ src/test/ui/nll/mir_check_cast_unsize.stderr | 4 +- .../projection-one-region-closure.stderr | 15 ++++++ ...tion-one-region-trait-bound-closure.stderr | 15 ++++++ ...tion-two-region-trait-bound-closure.stderr | 5 ++ 10 files changed, 103 insertions(+), 5 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 8505d8e1ef3..79165276430 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 @@ -15,10 +15,10 @@ use rustc::infer::InferCtxt; use rustc::mir::Mir; use rustc::ty::subst::{Substs, UnpackedKind}; -use rustc::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; use rustc::util::ppaux::with_highlight_region; use rustc_errors::DiagnosticBuilder; -use syntax::ast::Name; +use syntax::ast::{Name, DUMMY_NODE_ID}; use syntax::symbol::keywords; use syntax_pos::symbol::InternedString; @@ -90,14 +90,21 @@ fn give_name_from_error_region( diag: &mut DiagnosticBuilder<'_>, ) -> Option { let error_region = self.to_error_region(fr)?; + debug!("give_region_a_name: error_region = {:?}", error_region); match error_region { - ty::ReEarlyBound(ebr) => Some(ebr.name), + ty::ReEarlyBound(ebr) => { + self.highlight_named_span(tcx, error_region, &ebr.name, diag); + Some(ebr.name) + }, ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()), ty::ReFree(free_region) => match free_region.bound_region { - ty::BoundRegion::BrNamed(_, name) => Some(name), + ty::BoundRegion::BrNamed(_, name) => { + self.highlight_named_span(tcx, error_region, &name, diag); + Some(name) + }, ty::BoundRegion::BrEnv => { let closure_span = tcx.hir.span_if_local(mir_def_id).unwrap(); @@ -123,6 +130,45 @@ fn give_name_from_error_region( } } + /// Highlight a named span to provide context for error messages that + /// mention that span, for example: + /// + /// ``` + /// | + /// | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + /// | -- -- lifetime `'b` defined here + /// | | + /// | lifetime `'a` defined here + /// | + /// | with_signature(cell, t, |cell, t| require(cell, t)); + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must + /// | outlive `'a` + /// ``` + fn highlight_named_span( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + error_region: &RegionKind, + name: &InternedString, + diag: &mut DiagnosticBuilder<'_>, + ) { + let cm = tcx.sess.codemap(); + + let scope = error_region.free_region_binding_scope(tcx); + let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); + + let mut sp = cm.def_span(tcx.hir.span(node)); + if let Some(param) = tcx.hir.get_generics(scope).and_then(|generics| { + generics.get_named(name) + }) { + sp = param.span; + } + + diag.span_label( + sp, + format!("lifetime `{}` defined here", name), + ); + } + /// Find an argument that contains `fr` and label it with a fully /// elaborated type, returning something like `'1`. Result looks /// like: diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index bbc63e6feca..c1e12978c51 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -21,6 +21,8 @@ LL | self.x.iter().map(|a| a.0) error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:21:9 | +LL | fn iter_values<'a>(&'a self) -> impl Iterator { + | -- lifetime `'a` defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^ requires that `'a` must outlive `'static` diff --git a/src/test/ui/issue-10291.nll.stderr b/src/test/ui/issue-10291.nll.stderr index 6de00ffd48c..48dad040f9d 100644 --- a/src/test/ui/issue-10291.nll.stderr +++ b/src/test/ui/issue-10291.nll.stderr @@ -7,6 +7,8 @@ LL | x //~ ERROR E0312 error: unsatisfied lifetime constraints --> $DIR/issue-10291.rs:12:5 | +LL | fn test<'x>(x: &'x isize) { + | -- lifetime `'x` defined here LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static` diff --git a/src/test/ui/issue-52213.nll.stderr b/src/test/ui/issue-52213.nll.stderr index 7dd513d1b71..4e1efc96490 100644 --- a/src/test/ui/issue-52213.nll.stderr +++ b/src/test/ui/issue-52213.nll.stderr @@ -7,6 +7,11 @@ LL | match (&t,) { //~ ERROR cannot infer an appropriate lifetime error: unsatisfied lifetime constraints --> $DIR/issue-52213.rs:13:11 | +LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | match (&t,) { //~ ERROR cannot infer an appropriate lifetime LL | ((u,),) => u, | ^ requires that `'a` must outlive `'b` diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr index b0562711627..116ff6ef023 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -7,6 +7,8 @@ LL | &*x error: unsatisfied lifetime constraints --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 | +LL | fn foo<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here LL | &*x | ^^^ requires that `'a` must outlive `'static` diff --git a/src/test/ui/nll/mir_check_cast_closure.stderr b/src/test/ui/nll/mir_check_cast_closure.stderr index fc2a3c43f75..cdc407985fe 100644 --- a/src/test/ui/nll/mir_check_cast_closure.stderr +++ b/src/test/ui/nll/mir_check_cast_closure.stderr @@ -7,6 +7,10 @@ LL | g error: unsatisfied lifetime constraints --> $DIR/mir_check_cast_closure.rs:16:28 | +LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here LL | let g: fn(_, _) -> _ = |_x, y| y; | ^^^^^^^^^ cast requires that `'b` must outlive `'a` diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr index 7bd0595f3b5..02ecd05e5f9 100644 --- a/src/test/ui/nll/mir_check_cast_unsize.stderr +++ b/src/test/ui/nll/mir_check_cast_unsize.stderr @@ -8,7 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/mir_check_cast_unsize.rs:17:46 | LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug { - | ______________________________________________^ + | ________--____________________________________^ + | | | + | | lifetime `'a` defined here LL | | //~^ ERROR unsatisfied lifetime constraints LL | | x LL | | //~^ WARNING not reporting region error due to nll diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index ed8491349a2..2b0e682f851 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -52,6 +52,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-one-region-closure.rs:55:5 | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` @@ -101,6 +106,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-one-region-closure.rs:67:5 | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` @@ -150,6 +160,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-one-region-closure.rs:89:5 | +LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 8318ce10745..739bde4a481 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -51,6 +51,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-one-region-trait-bound-closure.rs:47:5 | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` @@ -91,6 +96,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-one-region-trait-bound-closure.rs:58:5 | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` @@ -131,6 +141,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-one-region-trait-bound-closure.rs:79:5 | +LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 1452573d57a..6838e0f3b3d 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -259,6 +259,11 @@ LL | | } error: unsatisfied lifetime constraints --> $DIR/projection-two-region-trait-bound-closure.rs:108:5 | +LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` -- 2.44.0