Skip to content

Commit c3521fe

Browse files
committed
Custom lifetime error for impl item doesn't conform to trait
1 parent d3d28a4 commit c3521fe

10 files changed

+93
-48
lines changed

src/librustc/infer/error_reporting/nice_region_error/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod named_anon_conflict;
1212
mod placeholder_error;
1313
mod outlives_closure;
1414
mod static_impl_trait;
15+
mod trait_impl_difference;
1516
mod util;
1617

1718
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
@@ -73,6 +74,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
7374
.or_else(|| self.try_report_anon_anon_conflict())
7475
.or_else(|| self.try_report_outlives_closure())
7576
.or_else(|| self.try_report_static_impl_trait())
77+
.or_else(|| self.try_report_impl_not_conforming_to_trait())
7678
}
7779

7880
pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
2+
3+
use crate::infer::{ValuePairs, Subtype};
4+
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5+
use crate::infer::lexical_region_resolve::RegionResolutionError;
6+
use crate::util::common::ErrorReported;
7+
8+
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
9+
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
10+
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
11+
if let Some(ref error) = self.error {
12+
if let RegionResolutionError::SubSupConflict(
13+
_,
14+
var_origin,
15+
sub_origin,
16+
_sub,
17+
sup_origin,
18+
_sup,
19+
) = error.clone() {
20+
match (&sup_origin, &sub_origin) {
21+
(&Subtype(ref sup_trace), &Subtype(ref sub_trace)) => {
22+
if let (
23+
ValuePairs::Types(sub_expected_found),
24+
ValuePairs::Types(sup_expected_found),
25+
) = (&sub_trace.values, &sup_trace.values) {
26+
if sup_expected_found == sub_expected_found {
27+
let sp = var_origin.span();
28+
let mut err = self.tcx().sess.struct_span_err(
29+
sp,
30+
"`impl` item doesn't match `trait` item"
31+
);
32+
err.note(&format!(
33+
"expected: {:?}\n found: {:?}",
34+
sub_expected_found.expected,
35+
sub_expected_found.found,
36+
));
37+
err.span_label(sp, &format!(
38+
"found {:?}",
39+
sub_expected_found.found,
40+
));
41+
// FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it.
42+
err.emit();
43+
return Some(ErrorReported);
44+
}
45+
}
46+
}
47+
_ => {}
48+
}
49+
}
50+
}
51+
None
52+
}
53+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ impl Deref for Struct {
99
unimplemented!();
1010
}
1111
}
12-
//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter
12+
//~^^^^ ERROR `impl` item doesn't match `trait` item
1313

1414
fn main() {}

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

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
1+
error: `impl` item doesn't match `trait` item
22
--> $DIR/mismatched_trait_impl-2.rs:8:5
33
|
44
LL | fn deref(&self) -> &dyn Trait {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait
66
|
7-
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
8-
--> $DIR/mismatched_trait_impl-2.rs:8:5
9-
|
10-
LL | / fn deref(&self) -> &dyn Trait {
11-
LL | | unimplemented!();
12-
LL | | }
13-
| |_____^
14-
= note: ...but the lifetime must also be valid for the static lifetime...
15-
= note: ...so that the method type is compatible with trait:
16-
expected fn(&Struct) -> &(dyn Trait + 'static)
17-
found fn(&Struct) -> &dyn Trait
7+
= note: expected: fn(&Struct) -> &(dyn Trait + 'static)
8+
found: fn(&Struct) -> &dyn Trait
189

1910
error: aborting due to previous error
2011

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ trait Get {
66
}
77

88
impl Get for i32 {
9-
fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
9+
fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR `impl` item doesn't match `trait`
1010
x //~ ERROR lifetime mismatch
1111
}
1212
}

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
1-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
1+
error: `impl` item doesn't match `trait` item
22
--> $DIR/mismatched_trait_impl.rs:9:5
33
|
44
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
66
|
7-
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5...
8-
--> $DIR/mismatched_trait_impl.rs:9:5
9-
|
10-
LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
11-
LL | | x
12-
LL | | }
13-
| |_____^
14-
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
15-
--> $DIR/mismatched_trait_impl.rs:9:32
16-
|
17-
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
18-
| ^^
19-
= note: ...so that the method type is compatible with trait:
20-
expected fn(&i32, &'a u32, &u32) -> &'a u32
21-
found fn(&i32, &u32, &u32) -> &u32
7+
= note: expected: fn(&i32, &'a u32, &u32) -> &'a u32
8+
found: fn(&i32, &u32, &u32) -> &u32
229

2310
error[E0623]: lifetime mismatch
2411
--> $DIR/mismatched_trait_impl.rs:10:9
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait Foo {
2+
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
3+
}
4+
5+
impl Foo for () {
6+
fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
7+
//~^ ERROR `impl` item doesn't match `trait` item
8+
if x > y { x } else { y }
9+
}
10+
}
11+
12+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: `impl` item doesn't match `trait` item
2+
--> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
3+
|
4+
LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32
6+
|
7+
= note: expected: fn(&i32, &'a i32) -> &'a i32
8+
found: fn(&i32, &i32) -> &i32
9+
10+
error: aborting due to previous error
11+

src/test/ui/reject-specialized-drops-8142.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
5252
//~^ ERROR Implementations of Drop cannot be specialized
5353

5454
impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
55-
//~^ ERROR cannot infer an appropriate lifetime
55+
//~^ ERROR `impl` item doesn't match `trait` item
5656

5757
pub fn main() { }

src/test/ui/reject-specialized-drops-8142.stderr

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,14 @@ note: Use same sequence of generic type and region parameters that is on the str
8989
LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
9090
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9191

92-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements
92+
error: `impl` item doesn't match `trait` item
9393
--> $DIR/reject-specialized-drops-8142.rs:54:1
9494
|
9595
LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
96-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97-
|
98-
note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10...
99-
--> $DIR/reject-specialized-drops-8142.rs:17:10
100-
|
101-
LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
102-
| ^^^
103-
note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15...
104-
--> $DIR/reject-specialized-drops-8142.rs:17:15
96+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_>
10597
|
106-
LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
107-
| ^^^
108-
= note: ...so that the types are compatible:
109-
expected W<'l1, 'l2>
110-
found W<'_, '_>
98+
= note: expected: W<'l1, 'l2>
99+
found: W<'_, '_>
111100

112101
error: aborting due to 8 previous errors
113102

0 commit comments

Comments
 (0)