Point only at method signatures and point at trait

- On mismatch between impl and trait method, point at the trait
   signature.
 - Point only at the method signature instead of the whole body on
   trait/impl mismatch errors.
This commit is contained in:
Esteban Küber 2018-01-28 13:42:49 -08:00
parent 6c026997bf
commit 67696be160
14 changed files with 75 additions and 88 deletions

View File

@ -807,7 +807,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} }
}; };
let span = cause.span; let span = cause.span(&self.tcx);
diag.span_label(span, terr.to_string()); diag.span_label(span, terr.to_string());
if let Some((sp, msg)) = secondary_span { if let Some((sp, msg)) = secondary_span {
@ -842,7 +842,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
"did you mean `{}(/* fields */)`?", "did you mean `{}(/* fields */)`?",
self.tcx.item_path_str(def_id) self.tcx.item_path_str(def_id)
); );
diag.span_label(cause.span, message); diag.span_label(span, message);
} }
} }
} }
@ -870,7 +870,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
trace, trace,
terr); terr);
let span = trace.cause.span; let span = trace.cause.span(&self.tcx);
let failure_code = trace.cause.as_failure_code(terr); let failure_code = trace.cause.as_failure_code(terr);
let mut diag = match failure_code { let mut diag = match failure_code {
FailureCode::Error0317(failure_str) => { FailureCode::Error0317(failure_str) => {

View File

@ -100,6 +100,19 @@ pub struct ObligationCause<'tcx> {
pub code: ObligationCauseCode<'tcx> pub code: ObligationCauseCode<'tcx>
} }
impl<'tcx> ObligationCause<'tcx> {
pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
match self.code {
ObligationCauseCode::CompareImplMethodObligation { .. } |
ObligationCauseCode::MainFunctionType |
ObligationCauseCode::StartFunctionType => {
tcx.sess.codemap().def_span(self.span)
}
_ => self.span,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum ObligationCauseCode<'tcx> { pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from span. /// Not well classified or should be obvious from span.

View File

@ -40,6 +40,8 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("compare_impl_method(impl_trait_ref={:?})", debug!("compare_impl_method(impl_trait_ref={:?})",
impl_trait_ref); impl_trait_ref);
let impl_m_span = tcx.sess.codemap().def_span(impl_m_span);
if let Err(ErrorReported) = compare_self_type(tcx, if let Err(ErrorReported) = compare_self_type(tcx,
impl_m, impl_m,
impl_m_span, impl_m_span,
@ -186,6 +188,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
check_region_bounds_on_impl_method(tcx, check_region_bounds_on_impl_method(tcx,
impl_m_span, impl_m_span,
impl_m, impl_m,
trait_m,
&trait_m_generics, &trait_m_generics,
&impl_m_generics, &impl_m_generics,
trait_to_skol_substs)?; trait_to_skol_substs)?;
@ -310,7 +313,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}; };
let mut diag = struct_span_err!(tcx.sess, let mut diag = struct_span_err!(tcx.sess,
cause.span, cause.span(&tcx),
E0053, E0053,
"method `{}` has an incompatible type for trait", "method `{}` has an incompatible type for trait",
trait_m.name); trait_m.name);
@ -346,10 +349,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span: Span, span: Span,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
trait_m: &ty::AssociatedItem,
trait_generics: &ty::Generics, trait_generics: &ty::Generics,
impl_generics: &ty::Generics, impl_generics: &ty::Generics,
trait_to_skol_substs: &Substs<'tcx>) trait_to_skol_substs: &Substs<'tcx>)
-> Result<(), ErrorReported> { -> Result<(), ErrorReported> {
let span = tcx.sess.codemap().def_span(span);
let trait_params = &trait_generics.regions[..]; let trait_params = &trait_generics.regions[..];
let impl_params = &impl_generics.regions[..]; let impl_params = &impl_generics.regions[..];
@ -371,14 +376,18 @@ 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 // are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message. // the moment, give a kind of vague error message.
if trait_params.len() != impl_params.len() { if trait_params.len() != impl_params.len() {
struct_span_err!(tcx.sess, let mut err = struct_span_err!(tcx.sess,
span, span,
E0195, E0195,
"lifetime parameters or bounds on method `{}` do not match the \ "lifetime parameters or bounds on method `{}` do not match \
trait declaration", the trait declaration",
impl_m.name) impl_m.name);
.span_label(span, "lifetimes do not match trait") err.span_label(span, "lifetimes do not match method in trait");
.emit(); 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");
}
err.emit();
return Err(ErrorReported); return Err(ErrorReported);
} }
@ -424,9 +433,9 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
}).map(|(ref impl_arg, ref trait_arg)| { }).map(|(ref impl_arg, ref trait_arg)| {
(impl_arg.span, Some(trait_arg.span)) (impl_arg.span, Some(trait_arg.span))
}) })
.unwrap_or_else(|| (cause.span, tcx.hir.span_if_local(trait_m.def_id))) .unwrap_or_else(|| (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)))
} else { } else {
(cause.span, tcx.hir.span_if_local(trait_m.def_id)) (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
} }
} }
TypeError::Sorts(ExpectedFound { .. }) => { TypeError::Sorts(ExpectedFound { .. }) => {
@ -459,14 +468,14 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
{ {
(impl_m_output.span(), Some(trait_m_output.span())) (impl_m_output.span(), Some(trait_m_output.span()))
} else { } else {
(cause.span, tcx.hir.span_if_local(trait_m.def_id)) (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
} }
}) })
} else { } else {
(cause.span, tcx.hir.span_if_local(trait_m.def_id)) (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
} }
} }
_ => (cause.span, tcx.hir.span_if_local(trait_m.def_id)), _ => (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)),
} }
} }

View File

@ -10,13 +10,14 @@
trait Trait { trait Trait {
fn bar<'a,'b:'a>(x: &'a str, y: &'b str); fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
//~^ NOTE lifetimes in impl do not match this method in trait
} }
struct Foo; struct Foo;
impl Trait for Foo { impl Trait for Foo {
fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
//~^ lifetimes do not match trait //~^ NOTE lifetimes do not match method in trait
} }
} }

View File

@ -10,6 +10,7 @@
trait NoLifetime { trait NoLifetime {
fn get<'p, T : Test<'p>>(&self) -> T; fn get<'p, T : Test<'p>>(&self) -> T;
//~^ NOTE lifetimes in impl do not match this method in trait
} }
trait Test<'p> { trait Test<'p> {
@ -28,8 +29,8 @@ impl<'a> Test<'a> for Foo<'a> {
impl<'a> NoLifetime for Foo<'a> { impl<'a> NoLifetime for Foo<'a> {
fn get<'p, T : Test<'a>>(&self) -> T { fn get<'p, T : Test<'a>>(&self) -> T {
//~^ ERROR E0195 //~^ ERROR E0195
//~| lifetimes do not match trait //~| NOTE lifetimes do not match method in trait
return *self as T; return *self as T;
} }
} }

View File

@ -9,11 +9,8 @@ error[E0308]: mismatched types
note: the lifetime 'a as defined on the impl at 17:1... note: the lifetime 'a as defined on the impl at 17:1...
--> $DIR/associated-const-impl-wrong-lifetime.rs:17:1 --> $DIR/associated-const-impl-wrong-lifetime.rs:17:1
| |
17 | / impl<'a> Foo for &'a () { 17 | impl<'a> Foo for &'a () {
18 | | const NAME: &'a str = "unit"; | ^^^^^^^^^^^^^^^^^^^^^^^
19 | | //~^ ERROR mismatched types [E0308]
20 | | }
| |_^
= note: ...does not necessarily outlive the static lifetime = note: ...does not necessarily outlive the static lifetime
error: aborting due to previous error error: aborting due to previous error

View File

@ -1,30 +1,26 @@
error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration 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:28:5
| |
28 | / fn no_bound<'b:'a>(self, b: Inv<'b>) { 20 | fn no_bound<'b>(self, b: Inv<'b>);
29 | | //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match | ---------------------------------- lifetimes in impl do not match this method in trait
30 | | } ...
| |_____^ lifetimes do not match trait 28 | fn no_bound<'b:'a>(self, b: Inv<'b>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration 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:32:5
| |
32 | / fn has_bound<'b>(self, b: Inv<'b>) { 21 | fn has_bound<'b:'a>(self, b: Inv<'b>);
33 | | //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match | -------------------------------------- lifetimes in impl do not match this method in trait
34 | | } ...
| |_____^ lifetimes do not match trait 32 | fn has_bound<'b>(self, b: Inv<'b>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
error[E0308]: method not compatible with 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:36:5
| |
36 | / fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { 36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
37 | | //~^ ERROR method not compatible with trait | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
38 | | //
39 | | // Note: This is a terrible error message. It is caused
... |
47 | | // cases.
48 | | }
| |_____^ lifetime mismatch
| |
= note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)` = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)` found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`

View File

@ -2,7 +2,7 @@ error[E0053]: method `fmt` has an incompatible type for trait
--> $DIR/trait_type.rs:17:4 --> $DIR/trait_type.rs:17:4
| |
17 | fn fmt(&self, x: &str) -> () { } 17 | fn fmt(&self, x: &str) -> () { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
| |
= note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` = note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
found type `fn(&MyType, &str)` found type `fn(&MyType, &str)`
@ -19,7 +19,7 @@ error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in th
--> $DIR/trait_type.rs:27:4 --> $DIR/trait_type.rs:27:4
| |
27 | fn fmt() -> () { } 27 | fn fmt() -> () { }
| ^^^^^^^^^^^^^^^^^^ expected `&self` in impl | ^^^^^^^^^^^^^^ expected `&self` in impl
| |
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`

View File

@ -3,10 +3,8 @@ error[E0601]: main function not found
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
--> $DIR/mismatched_trait_impl-2.rs:18:5 --> $DIR/mismatched_trait_impl-2.rs:18:5
| |
18 | / fn deref(&self) -> &Trait { 18 | fn deref(&self) -> &Trait {
19 | | unimplemented!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^
20 | | }
| |_____^
| |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5... note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
--> $DIR/mismatched_trait_impl-2.rs:18:5 --> $DIR/mismatched_trait_impl-2.rs:18:5

View File

@ -1,10 +1,8 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
--> $DIR/mismatched_trait_impl.rs:19:5 --> $DIR/mismatched_trait_impl.rs:19:5
| |
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer 19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
20 | | x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21 | | }
| |_____^
| |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5... note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5...
--> $DIR/mismatched_trait_impl.rs:19:5 --> $DIR/mismatched_trait_impl.rs:19:5

View File

@ -14,14 +14,8 @@ note: the anonymous lifetime #1 defined on the method body at 15:5...
note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 13:1 note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 13:1
--> $DIR/issue-27942.rs:13:1 --> $DIR/issue-27942.rs:13:1
| |
13 | / pub trait Buffer<'a, R: Resources<'a>> { 13 | pub trait Buffer<'a, R: Resources<'a>> {
14 | | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | | fn select(&self) -> BufferViewHandle<R>;
16 | | //~^ ERROR mismatched types
... |
19 | | //~| lifetime mismatch
20 | | }
| |_^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-27942.rs:15:5 --> $DIR/issue-27942.rs:15:5
@ -34,14 +28,8 @@ error[E0308]: mismatched types
note: the lifetime 'a as defined on the trait at 13:1... note: the lifetime 'a as defined on the trait at 13:1...
--> $DIR/issue-27942.rs:13:1 --> $DIR/issue-27942.rs:13:1
| |
13 | / pub trait Buffer<'a, R: Resources<'a>> { 13 | pub trait Buffer<'a, R: Resources<'a>> {
14 | | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | | fn select(&self) -> BufferViewHandle<R>;
16 | | //~^ ERROR mismatched types
... |
19 | | //~| lifetime mismatch
20 | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 15:5 note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 15:5
--> $DIR/issue-27942.rs:15:5 --> $DIR/issue-27942.rs:15:5
| |

View File

@ -24,14 +24,8 @@ note: the anonymous lifetime #1 defined on the method body at 16:5...
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1 note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1
--> $DIR/issue-37884.rs:13:1 --> $DIR/issue-37884.rs:13:1
| |
13 | / impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { 13 | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
14 | | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | | type Item = &'a mut T;
16 | | fn next(&'a mut self) -> Option<Self::Item>
... |
21 | | }
22 | | }
| |_^
error: aborting due to previous error error: aborting due to previous error

View File

@ -10,12 +10,8 @@ error[E0597]: borrowed value does not live long enough (Ast)
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1... note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
--> $DIR/issue-46472.rs:13:1 --> $DIR/issue-46472.rs:13:1
| |
13 | / fn bar<'a>() -> &'a mut u32 { 13 | fn bar<'a>() -> &'a mut u32 {
14 | | &mut 4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
17 | | }
| |_^
error[E0597]: borrowed value does not live long enough (Mir) error[E0597]: borrowed value does not live long enough (Mir)
--> $DIR/issue-46472.rs:14:10 --> $DIR/issue-46472.rs:14:10
@ -29,12 +25,8 @@ error[E0597]: borrowed value does not live long enough (Mir)
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1... note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
--> $DIR/issue-46472.rs:13:1 --> $DIR/issue-46472.rs:13:1
| |
13 | / fn bar<'a>() -> &'a mut u32 { 13 | fn bar<'a>() -> &'a mut u32 {
14 | | &mut 4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
17 | | }
| |_^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -8,7 +8,7 @@ note: lifetime parameter instantiated with the lifetime 'a as defined on the imp
--> $DIR/static-lifetime.rs:13:1 --> $DIR/static-lifetime.rs:13:1
| |
13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound 13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: but lifetime parameter must outlive the static lifetime = note: but lifetime parameter must outlive the static lifetime
error: aborting due to previous error error: aborting due to previous error