Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Point to lifetime spans on lifetime errors #51862

Merged
merged 6 commits into from
Jun 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_target::spec::abi::Abi;
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
use syntax::codemap::Spanned;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use syntax_pos::{Span, DUMMY_SP};

use hir::*;
use hir::print::Nested;
Expand Down Expand Up @@ -664,6 +664,33 @@ impl<'hir> Map<'hir> {
self.as_local_node_id(id).map(|id| self.get(id)) // read recorded by `get`
}

pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> {
self.get_if_local(id).and_then(|node| {
match node {
NodeImplItem(ref impl_item) => Some(&impl_item.generics),
NodeTraitItem(ref trait_item) => Some(&trait_item.generics),
NodeItem(ref item) => {
match item.node {
ItemFn(_, _, ref generics, _) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
ItemUnion(_, ref generics) |
ItemTrait(_, _, ref generics, ..) |
ItemTraitAlias(ref generics, _) |
ItemImpl(_, _, _, ref generics, ..) => Some(generics),
_ => None,
}
}
_ => None,
}
})
}

pub fn get_generics_span(&self, id: DefId) -> Option<Span> {
self.get_generics(id).map(|generics| generics.span).filter(|sp| *sp != DUMMY_SP)
}

/// Retrieve the Node corresponding to `id`, returning None if
/// cannot be found.
pub fn find(&self, id: NodeId) -> Option<Node<'hir>> {
Expand Down
11 changes: 10 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
use util::nodemap::{NodeMap, FxHashSet};
use mir::mono::Linkage;

use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
use syntax::codemap::{self, Spanned};
use rustc_target::spec::abi::Abi;
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
Expand Down Expand Up @@ -547,6 +547,15 @@ impl Generics {

own_counts
}

pub fn get_named(&self, name: &InternedString) -> Option<&GenericParam> {
for param in &self.params {
if *name == param.name.ident().as_interned_str() {
return Some(param);
}
}
None
}
}

/// Synthetic Type Parameters are converted to an other form during lowering, this allows
Expand Down
28 changes: 23 additions & 5 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self,
region: ty::Region<'tcx>,
) -> (String, Option<Span>) {
let cm = self.sess.codemap();

let scope = region.free_region_binding_scope(self);
let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID);
let unknown;
Expand Down Expand Up @@ -219,10 +221,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
};
let (prefix, span) = match *region {
ty::ReEarlyBound(ref br) => (
format!("the lifetime {} as defined on", br.name),
self.sess.codemap().def_span(self.hir.span(node)),
),
ty::ReEarlyBound(ref br) => {
let mut sp = cm.def_span(self.hir.span(node));
if let Some(param) = self.hir.get_generics(scope).and_then(|generics| {
generics.get_named(&br.name)
}) {
sp = param.span;
}
(format!("the lifetime {} as defined on", br.name), sp)
}
ty::ReFree(ty::FreeRegion {
bound_region: ty::BoundRegion::BrNamed(_, ref name), ..
}) => {
let mut sp = cm.def_span(self.hir.span(node));
if let Some(param) = self.hir.get_generics(scope).and_then(|generics| {
generics.get_named(&name)
}) {
sp = param.span;
}
(format!("the lifetime {} as defined on", name), sp)
}
ty::ReFree(ref fr) => match fr.bound_region {
ty::BrAnon(idx) => (
format!("the anonymous lifetime #{} defined on", idx + 1),
Expand All @@ -234,7 +252,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
),
_ => (
format!("the lifetime {} as defined on", fr.bound_region),
self.sess.codemap().def_span(self.hir.span(node)),
cm.def_span(self.hir.span(node)),
),
},
_ => bug!(),
Expand Down
21 changes: 12 additions & 9 deletions src/librustc_typeck/check/compare_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,6 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_generics: &ty::Generics,
trait_to_skol_substs: &Substs<'tcx>)
-> Result<(), ErrorReported> {
let span = tcx.sess.codemap().def_span(span);
let trait_params = trait_generics.own_counts().lifetimes;
let impl_params = impl_generics.own_counts().lifetimes;

Expand All @@ -378,16 +377,20 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message.
if trait_params != impl_params {
let mut err = struct_span_err!(tcx.sess,
span,
E0195,
"lifetime parameters or bounds on method `{}` do not match \
the trait declaration",
impl_m.ident);
let def_span = tcx.sess.codemap().def_span(span);
let span = tcx.hir.get_generics_span(impl_m.def_id).unwrap_or(def_span);
let mut err = struct_span_err!(
tcx.sess,
span,
E0195,
"lifetime parameters or bounds on method `{}` do not match the trait declaration",
impl_m.ident,
);
err.span_label(span, "lifetimes do not match method in trait");
if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) {
err.span_label(tcx.sess.codemap().def_span(sp),
"lifetimes in impl do not match this method in trait");
let def_sp = tcx.sess.codemap().def_span(sp);
let sp = tcx.hir.get_generics_span(trait_m.def_id).unwrap_or(def_sp);
err.span_label(sp, "lifetimes in impl do not match this method in trait");
}
err.emit();
return Err(ErrorReported);
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/associated-const-impl-wrong-lifetime.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ LL | const NAME: &'a str = "unit";
|
= note: expected type `&'static str`
found type `&'a str`
note: the lifetime 'a as defined on the impl at 17:1...
--> $DIR/associated-const-impl-wrong-lifetime.rs:17:1
note: the lifetime 'a as defined on the impl at 17:6...
--> $DIR/associated-const-impl-wrong-lifetime.rs:17:6
|
LL | impl<'a> Foo for &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^
| ^^
= note: ...does not necessarily outlive the static lifetime

error: aborting due to previous error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ LL | //~^ ERROR E0373
LL | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 19:1...
--> $DIR/borrowck-escaping-closure-error-2.rs:19:1
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 19:8...
--> $DIR/borrowck-escaping-closure-error-2.rs:19:8
|
LL | fn foo<'a>(x: &'a i32) -> Box<FnMut()+'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^

error: aborting due to previous error

Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub trait Foo<'a, 't> {
fn no_bound<'b>(self, b: Inv<'b>);
fn has_bound<'b:'a>(self, b: Inv<'b>);
fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
}
Expand Down Expand Up @@ -47,6 +48,10 @@ impl<'a, 't> Foo<'a, 't> for &'a isize {
// cases.
}

fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
//~^ ERROR lifetime parameters or bounds on method `wrong_bound2` do not match the trait
}

fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
}

Expand Down
39 changes: 24 additions & 15 deletions src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
Original file line number Diff line number Diff line change
@@ -1,50 +1,59 @@
error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration
--> $DIR/regions-bound-missing-bound-in-impl.rs:28:5
--> $DIR/regions-bound-missing-bound-in-impl.rs:29:16
|
LL | fn no_bound<'b>(self, b: Inv<'b>);
| ---------------------------------- lifetimes in impl do not match this method in trait
| ---- lifetimes in impl do not match this method in trait
...
LL | fn no_bound<'b:'a>(self, b: Inv<'b>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
| ^^^^^^^ lifetimes do not match method in trait

error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration
--> $DIR/regions-bound-missing-bound-in-impl.rs:32:5
--> $DIR/regions-bound-missing-bound-in-impl.rs:33:17
|
LL | fn has_bound<'b:'a>(self, b: Inv<'b>);
| -------------------------------------- lifetimes in impl do not match this method in trait
| ------- lifetimes in impl do not match this method in trait
...
LL | fn has_bound<'b>(self, b: Inv<'b>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
| ^^^^ lifetimes do not match method in trait

error[E0308]: method not compatible with trait
--> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
--> $DIR/regions-bound-missing-bound-in-impl.rs:37:5
|
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`
note: the lifetime 'c as defined on the method body at 36:5...
--> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
note: the lifetime 'c as defined on the method body at 37:24...
--> $DIR/regions-bound-missing-bound-in-impl.rs:37:24
|
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 36:5
--> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
| ^^
note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 37:24
--> $DIR/regions-bound-missing-bound-in-impl.rs:37:24
|
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^

error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
--> $DIR/regions-bound-missing-bound-in-impl.rs:51:5
|
LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
| ---------------- lifetimes in impl do not match this method in trait
...
LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait

error[E0276]: impl has stricter requirements than trait
--> $DIR/regions-bound-missing-bound-in-impl.rs:53:5
--> $DIR/regions-bound-missing-bound-in-impl.rs:58:5
|
LL | fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
| ------------------------------------------------------- definition of `another_bound` from trait
...
LL | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't`

error: aborting due to 4 previous errors
error: aborting due to 5 previous errors

Some errors occurred: E0195, E0276, E0308.
For more information about an error, try `rustc --explain E0195`.
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ LL | |
LL | | //~^ ERROR borrowed data cannot be stored outside of its closure
LL | | });
| |_____^
note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1
--> $DIR/expect-region-supply-region.rs:42:1
note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:30
--> $DIR/expect-region-supply-region.rs:42:30
|
LL | fn expect_bound_supply_named<'x>() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^

error[E0308]: mismatched types
--> $DIR/expect-region-supply-region.rs:47:33
Expand All @@ -52,11 +52,11 @@ LL | closure_expecting_bound(|x: &'x u32| {
|
= note: expected type `&u32`
found type `&'x u32`
note: the lifetime 'x as defined on the function body at 42:1...
--> $DIR/expect-region-supply-region.rs:42:1
note: the lifetime 'x as defined on the function body at 42:30...
--> $DIR/expect-region-supply-region.rs:42:30
|
LL | fn expect_bound_supply_named<'x>() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29
--> $DIR/expect-region-supply-region.rs:47:29
|
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/error-codes/E0195.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration
--> $DIR/E0195.rs:19:5
--> $DIR/E0195.rs:19:11
|
LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
| ----------------------------------------- lifetimes in impl do not match this method in trait
| ---------- lifetimes in impl do not match this method in trait
...
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
| ^^^^^^^ lifetimes do not match method in trait

error: aborting due to previous error

Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/error-codes/E0478.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ error[E0478]: lifetime bound not satisfied
LL | child: Box<Wedding<'kiss> + 'SnowWhite>, //~ ERROR E0478
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 13:1
--> $DIR/E0478.rs:13:1
note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 13:22
--> $DIR/E0478.rs:13:22
|
LL | struct Prince<'kiss, 'SnowWhite> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 13:1
--> $DIR/E0478.rs:13:1
| ^^^^^^^^^^
note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 13:15
--> $DIR/E0478.rs:13:15
|
LL | struct Prince<'kiss, 'SnowWhite> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^

error: aborting due to previous error

Expand Down
13 changes: 4 additions & 9 deletions src/test/ui/impl-trait/region-escape-via-bound.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
| ^^^^^^^^^^^^^^
|
note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 26:1
--> $DIR/region-escape-via-bound.rs:26:1
note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 28:7
--> $DIR/region-escape-via-bound.rs:28:7
|
LL | / fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
LL | | //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
LL | | where 'x: 'y
LL | | {
LL | | x
LL | | }
| |_^
LL | where 'x: 'y
| ^^

error: aborting due to previous error

Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/impl-trait/static-return-lifetime-infered.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ LL | self.x.iter().map(|a| a.0)
| |
| ...but this borrow...
|
note: ...can't outlive the lifetime 'a as defined on the method body at 20:5
--> $DIR/static-return-lifetime-infered.rs:20:5
note: ...can't outlive the lifetime 'a as defined on the method body at 20:20
--> $DIR/static-return-lifetime-infered.rs:20:20
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 20:5
| ^^
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 20:20
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
LL | static_val(x); //~ ERROR cannot infer
| ^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 31:1...
--> $DIR/dyn-trait.rs:31:1
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 31:26...
--> $DIR/dyn-trait.rs:31:26
|
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^
= note: ...so that the expression is assignable:
expected std::boxed::Box<dyn std::fmt::Debug>
found std::boxed::Box<(dyn std::fmt::Debug + 'a)>
Expand Down
Loading