Skip to content

Commit 0b7e28a

Browse files
committed
Auto merge of #65068 - estebank:trait-impl-lt-mismatch, r=nikomatsakis
Custom lifetime error for `impl` item doesn't conform to `trait` Partly addresses #42706, #41343, fix #40900.
2 parents aa69777 + 213fd1f commit 0b7e28a

10 files changed

+115
-53
lines changed

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

+2
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>) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
2+
3+
use syntax_pos::Span;
4+
use crate::ty::Ty;
5+
use crate::infer::{ValuePairs, Subtype};
6+
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
7+
use crate::infer::lexical_region_resolve::RegionResolutionError;
8+
use crate::util::common::ErrorReported;
9+
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
10+
11+
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
12+
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
13+
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
14+
if let Some(ref error) = self.error {
15+
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
16+
if let RegionResolutionError::SubSupConflict(
17+
_,
18+
var_origin,
19+
sub_origin,
20+
_sub,
21+
sup_origin,
22+
_sup,
23+
) = error.clone() {
24+
match (&sup_origin, &sub_origin) {
25+
(&Subtype(ref sup_trace), &Subtype(ref sub_trace)) => {
26+
if let (
27+
ValuePairs::Types(sub_expected_found),
28+
ValuePairs::Types(sup_expected_found),
29+
CompareImplMethodObligation { trait_item_def_id, .. },
30+
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) {
31+
if sup_expected_found == sub_expected_found {
32+
self.emit_err(
33+
var_origin.span(),
34+
sub_expected_found.expected,
35+
sub_expected_found.found,
36+
self.tcx().def_span(*trait_item_def_id),
37+
);
38+
return Some(ErrorReported);
39+
}
40+
}
41+
}
42+
_ => {}
43+
}
44+
}
45+
}
46+
None
47+
}
48+
49+
fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Span) {
50+
let mut err = self.tcx().sess.struct_span_err(
51+
sp,
52+
"`impl` item signature doesn't match `trait` item signature",
53+
);
54+
err.note(&format!("expected `{:?}`\n found `{:?}`", expected, found));
55+
err.span_label(sp, &format!("found {:?}", found));
56+
err.span_label(impl_sp, &format!("expected {:?}", expected));
57+
err.emit();
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// ignore-x86
2+
// ^ due to stderr output differences
13
use std::ops::Deref;
24
trait Trait {}
35

@@ -6,9 +8,9 @@ struct Struct;
68
impl Deref for Struct {
79
type Target = dyn Trait;
810
fn deref(&self) -> &dyn Trait {
11+
//~^ ERROR `impl` item signature doesn't match `trait` item signature
912
unimplemented!();
1013
}
1114
}
12-
//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter
1315

1416
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
1-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
2-
--> $DIR/mismatched_trait_impl-2.rs:8:5
1+
error: `impl` item signature doesn't match `trait` item signature
2+
--> $DIR/mismatched_trait_impl-2.rs:10:5
33
|
44
LL | fn deref(&self) -> &dyn Trait {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait
6+
|
7+
::: $SRC_DIR/libcore/ops/deref.rs:LL:COL
68
|
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+
LL | fn deref(&self) -> &Self::Target;
10+
| --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static)
911
|
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
12+
= note: expected `fn(&Struct) -> &(dyn Trait + 'static)`
13+
found `fn(&Struct) -> &dyn Trait`
1814

1915
error: aborting due to previous error
2016

21-
For more information about this error, try `rustc --explain E0495`.
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
1-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
1+
error: `impl` item signature doesn't match `trait` item signature
22
--> $DIR/mismatched_trait_impl.rs:9:5
33
|
4+
LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
5+
| ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
6+
...
47
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
69
|
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
10+
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
11+
found `fn(&i32, &u32, &u32) -> &u32`
2212

2313
error: aborting due to previous error
2414

25-
For more information about this error, try `rustc --explain E0495`.

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

+1-1
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 signature doesn't match
1010
x //~ ERROR lifetime mismatch
1111
}
1212
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,14 @@
1-
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
1+
error: `impl` item signature doesn't match `trait` item signature
22
--> $DIR/mismatched_trait_impl.rs:9:5
33
|
4+
LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
5+
| ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
6+
...
47
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
69
|
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
10+
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
11+
found `fn(&i32, &u32, &u32) -> &u32`
2212

2313
error[E0623]: lifetime mismatch
2414
--> $DIR/mismatched_trait_impl.rs:10:9
@@ -32,4 +22,3 @@ LL | x
3222

3323
error: aborting due to 2 previous errors
3424

35-
For more information about this error, try `rustc --explain E0495`.
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 signature doesn't match `trait` item signature
8+
if x > y { x } else { y }
9+
}
10+
}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `impl` item signature doesn't match `trait` item signature
2+
--> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
3+
|
4+
LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
5+
| ------------------------------------------- expected fn(&i32, &'a i32) -> &'a i32
6+
...
7+
LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32
9+
|
10+
= note: expected `fn(&i32, &'a i32) -> &'a i32`
11+
found `fn(&i32, &i32) -> &i32`
12+
13+
error: aborting due to previous error
14+

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

+1-1
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 cannot infer an appropriate lifetime for lifetime parameter `'lw`
5656

5757
pub fn main() { }

0 commit comments

Comments
 (0)