Skip to content

Commit 67696be

Browse files
committed
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.
1 parent 6c02699 commit 67696be

14 files changed

+75
-88
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
807807
}
808808
};
809809

810-
let span = cause.span;
810+
let span = cause.span(&self.tcx);
811811

812812
diag.span_label(span, terr.to_string());
813813
if let Some((sp, msg)) = secondary_span {
@@ -842,7 +842,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
842842
"did you mean `{}(/* fields */)`?",
843843
self.tcx.item_path_str(def_id)
844844
);
845-
diag.span_label(cause.span, message);
845+
diag.span_label(span, message);
846846
}
847847
}
848848
}
@@ -870,7 +870,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
870870
trace,
871871
terr);
872872

873-
let span = trace.cause.span;
873+
let span = trace.cause.span(&self.tcx);
874874
let failure_code = trace.cause.as_failure_code(terr);
875875
let mut diag = match failure_code {
876876
FailureCode::Error0317(failure_str) => {

src/librustc/traits/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ pub struct ObligationCause<'tcx> {
100100
pub code: ObligationCauseCode<'tcx>
101101
}
102102

103+
impl<'tcx> ObligationCause<'tcx> {
104+
pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
105+
match self.code {
106+
ObligationCauseCode::CompareImplMethodObligation { .. } |
107+
ObligationCauseCode::MainFunctionType |
108+
ObligationCauseCode::StartFunctionType => {
109+
tcx.sess.codemap().def_span(self.span)
110+
}
111+
_ => self.span,
112+
}
113+
}
114+
}
115+
103116
#[derive(Clone, Debug, PartialEq, Eq)]
104117
pub enum ObligationCauseCode<'tcx> {
105118
/// Not well classified or should be obvious from span.

src/librustc_typeck/check/compare_method.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
4040
debug!("compare_impl_method(impl_trait_ref={:?})",
4141
impl_trait_ref);
4242

43+
let impl_m_span = tcx.sess.codemap().def_span(impl_m_span);
44+
4345
if let Err(ErrorReported) = compare_self_type(tcx,
4446
impl_m,
4547
impl_m_span,
@@ -186,6 +188,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
186188
check_region_bounds_on_impl_method(tcx,
187189
impl_m_span,
188190
impl_m,
191+
trait_m,
189192
&trait_m_generics,
190193
&impl_m_generics,
191194
trait_to_skol_substs)?;
@@ -310,7 +313,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
310313
};
311314

312315
let mut diag = struct_span_err!(tcx.sess,
313-
cause.span,
316+
cause.span(&tcx),
314317
E0053,
315318
"method `{}` has an incompatible type for trait",
316319
trait_m.name);
@@ -346,10 +349,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
346349
fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
347350
span: Span,
348351
impl_m: &ty::AssociatedItem,
352+
trait_m: &ty::AssociatedItem,
349353
trait_generics: &ty::Generics,
350354
impl_generics: &ty::Generics,
351355
trait_to_skol_substs: &Substs<'tcx>)
352356
-> Result<(), ErrorReported> {
357+
let span = tcx.sess.codemap().def_span(span);
353358
let trait_params = &trait_generics.regions[..];
354359
let impl_params = &impl_generics.regions[..];
355360

@@ -371,14 +376,18 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
371376
// are zero. Since I don't quite know how to phrase things at
372377
// the moment, give a kind of vague error message.
373378
if trait_params.len() != impl_params.len() {
374-
struct_span_err!(tcx.sess,
375-
span,
376-
E0195,
377-
"lifetime parameters or bounds on method `{}` do not match the \
378-
trait declaration",
379-
impl_m.name)
380-
.span_label(span, "lifetimes do not match trait")
381-
.emit();
379+
let mut err = struct_span_err!(tcx.sess,
380+
span,
381+
E0195,
382+
"lifetime parameters or bounds on method `{}` do not match \
383+
the trait declaration",
384+
impl_m.name);
385+
err.span_label(span, "lifetimes do not match method in trait");
386+
if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) {
387+
err.span_label(tcx.sess.codemap().def_span(sp),
388+
"lifetimes in impl do not match this method in trait");
389+
}
390+
err.emit();
382391
return Err(ErrorReported);
383392
}
384393

@@ -424,9 +433,9 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
424433
}).map(|(ref impl_arg, ref trait_arg)| {
425434
(impl_arg.span, Some(trait_arg.span))
426435
})
427-
.unwrap_or_else(|| (cause.span, tcx.hir.span_if_local(trait_m.def_id)))
436+
.unwrap_or_else(|| (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)))
428437
} else {
429-
(cause.span, tcx.hir.span_if_local(trait_m.def_id))
438+
(cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
430439
}
431440
}
432441
TypeError::Sorts(ExpectedFound { .. }) => {
@@ -459,14 +468,14 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
459468
{
460469
(impl_m_output.span(), Some(trait_m_output.span()))
461470
} else {
462-
(cause.span, tcx.hir.span_if_local(trait_m.def_id))
471+
(cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
463472
}
464473
})
465474
} else {
466-
(cause.span, tcx.hir.span_if_local(trait_m.def_id))
475+
(cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
467476
}
468477
}
469-
_ => (cause.span, tcx.hir.span_if_local(trait_m.def_id)),
478+
_ => (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)),
470479
}
471480
}
472481

src/test/compile-fail/E0195.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010

1111
trait Trait {
1212
fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
13+
//~^ NOTE lifetimes in impl do not match this method in trait
1314
}
1415

1516
struct Foo;
1617

1718
impl Trait for Foo {
1819
fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
19-
//~^ lifetimes do not match trait
20+
//~^ NOTE lifetimes do not match method in trait
2021
}
2122
}
2223

src/test/compile-fail/issue-16048.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
trait NoLifetime {
1212
fn get<'p, T : Test<'p>>(&self) -> T;
13+
//~^ NOTE lifetimes in impl do not match this method in trait
1314
}
1415

1516
trait Test<'p> {
@@ -28,8 +29,8 @@ impl<'a> Test<'a> for Foo<'a> {
2829

2930
impl<'a> NoLifetime for Foo<'a> {
3031
fn get<'p, T : Test<'a>>(&self) -> T {
31-
//~^ ERROR E0195
32-
//~| lifetimes do not match trait
32+
//~^ ERROR E0195
33+
//~| NOTE lifetimes do not match method in trait
3334
return *self as T;
3435
}
3536
}

src/test/ui/associated-const-impl-wrong-lifetime.stderr

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,8 @@ error[E0308]: mismatched types
99
note: the lifetime 'a as defined on the impl at 17:1...
1010
--> $DIR/associated-const-impl-wrong-lifetime.rs:17:1
1111
|
12-
17 | / impl<'a> Foo for &'a () {
13-
18 | | const NAME: &'a str = "unit";
14-
19 | | //~^ ERROR mismatched types [E0308]
15-
20 | | }
16-
| |_^
12+
17 | impl<'a> Foo for &'a () {
13+
| ^^^^^^^^^^^^^^^^^^^^^^^
1714
= note: ...does not necessarily outlive the static lifetime
1815

1916
error: aborting due to previous error

src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration
22
--> $DIR/regions-bound-missing-bound-in-impl.rs:28:5
33
|
4-
28 | / fn no_bound<'b:'a>(self, b: Inv<'b>) {
5-
29 | | //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
6-
30 | | }
7-
| |_____^ lifetimes do not match trait
4+
20 | fn no_bound<'b>(self, b: Inv<'b>);
5+
| ---------------------------------- lifetimes in impl do not match this method in trait
6+
...
7+
28 | fn no_bound<'b:'a>(self, b: Inv<'b>) {
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
89

910
error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration
1011
--> $DIR/regions-bound-missing-bound-in-impl.rs:32:5
1112
|
12-
32 | / fn has_bound<'b>(self, b: Inv<'b>) {
13-
33 | | //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
14-
34 | | }
15-
| |_____^ lifetimes do not match trait
13+
21 | fn has_bound<'b:'a>(self, b: Inv<'b>);
14+
| -------------------------------------- lifetimes in impl do not match this method in trait
15+
...
16+
32 | fn has_bound<'b>(self, b: Inv<'b>) {
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
1618

1719
error[E0308]: method not compatible with trait
1820
--> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
1921
|
20-
36 | / fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
21-
37 | | //~^ ERROR method not compatible with trait
22-
38 | | //
23-
39 | | // Note: This is a terrible error message. It is caused
24-
... |
25-
47 | | // cases.
26-
48 | | }
27-
| |_____^ lifetime mismatch
22+
36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
2824
|
2925
= note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
3026
found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`

src/test/ui/impl-trait/trait_type.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0053]: method `fmt` has an incompatible type for trait
22
--> $DIR/trait_type.rs:17:4
33
|
44
17 | fn fmt(&self, x: &str) -> () { }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
66
|
77
= note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
88
found type `fn(&MyType, &str)`
@@ -19,7 +19,7 @@ error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in th
1919
--> $DIR/trait_type.rs:27:4
2020
|
2121
27 | fn fmt() -> () { }
22-
| ^^^^^^^^^^^^^^^^^^ expected `&self` in impl
22+
| ^^^^^^^^^^^^^^ expected `&self` in impl
2323
|
2424
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
2525

src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ error[E0601]: main function not found
33
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
44
--> $DIR/mismatched_trait_impl-2.rs:18:5
55
|
6-
18 | / fn deref(&self) -> &Trait {
7-
19 | | unimplemented!();
8-
20 | | }
9-
| |_____^
6+
18 | fn deref(&self) -> &Trait {
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
108
|
119
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
1210
--> $DIR/mismatched_trait_impl-2.rs:18:5

src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
22
--> $DIR/mismatched_trait_impl.rs:19:5
33
|
4-
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
5-
20 | | x
6-
21 | | }
7-
| |_____^
4+
19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86
|
97
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5...
108
--> $DIR/mismatched_trait_impl.rs:19:5

src/test/ui/issue-27942.stderr

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,8 @@ note: the anonymous lifetime #1 defined on the method body at 15:5...
1414
note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 13:1
1515
--> $DIR/issue-27942.rs:13:1
1616
|
17-
13 | / pub trait Buffer<'a, R: Resources<'a>> {
18-
14 | |
19-
15 | | fn select(&self) -> BufferViewHandle<R>;
20-
16 | | //~^ ERROR mismatched types
21-
... |
22-
19 | | //~| lifetime mismatch
23-
20 | | }
24-
| |_^
17+
13 | pub trait Buffer<'a, R: Resources<'a>> {
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2519

2620
error[E0308]: mismatched types
2721
--> $DIR/issue-27942.rs:15:5
@@ -34,14 +28,8 @@ error[E0308]: mismatched types
3428
note: the lifetime 'a as defined on the trait at 13:1...
3529
--> $DIR/issue-27942.rs:13:1
3630
|
37-
13 | / pub trait Buffer<'a, R: Resources<'a>> {
38-
14 | |
39-
15 | | fn select(&self) -> BufferViewHandle<R>;
40-
16 | | //~^ ERROR mismatched types
41-
... |
42-
19 | | //~| lifetime mismatch
43-
20 | | }
44-
| |_^
31+
13 | pub trait Buffer<'a, R: Resources<'a>> {
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4533
note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 15:5
4634
--> $DIR/issue-27942.rs:15:5
4735
|

src/test/ui/issue-37884.stderr

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,8 @@ note: the anonymous lifetime #1 defined on the method body at 16:5...
2424
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1
2525
--> $DIR/issue-37884.rs:13:1
2626
|
27-
13 | / impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
28-
14 | |
29-
15 | | type Item = &'a mut T;
30-
16 | | fn next(&'a mut self) -> Option<Self::Item>
31-
... |
32-
21 | | }
33-
22 | | }
34-
| |_^
27+
13 | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3529

3630
error: aborting due to previous error
3731

src/test/ui/issue-46472.stderr

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,8 @@ error[E0597]: borrowed value does not live long enough (Ast)
1010
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
1111
--> $DIR/issue-46472.rs:13:1
1212
|
13-
13 | / fn bar<'a>() -> &'a mut u32 {
14-
14 | | &mut 4
15-
15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
16-
16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
17-
17 | | }
18-
| |_^
13+
13 | fn bar<'a>() -> &'a mut u32 {
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1915

2016
error[E0597]: borrowed value does not live long enough (Mir)
2117
--> $DIR/issue-46472.rs:14:10
@@ -29,12 +25,8 @@ error[E0597]: borrowed value does not live long enough (Mir)
2925
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
3026
--> $DIR/issue-46472.rs:13:1
3127
|
32-
13 | / fn bar<'a>() -> &'a mut u32 {
33-
14 | | &mut 4
34-
15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
35-
16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
36-
17 | | }
37-
| |_^
28+
13 | fn bar<'a>() -> &'a mut u32 {
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
3830

3931
error: aborting due to 2 previous errors
4032

src/test/ui/static-lifetime.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ note: lifetime parameter instantiated with the lifetime 'a as defined on the imp
88
--> $DIR/static-lifetime.rs:13:1
99
|
1010
13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212
= note: but lifetime parameter must outlive the static lifetime
1313

1414
error: aborting due to previous error

0 commit comments

Comments
 (0)