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

Custom lifetime error for impl item doesn't conform to trait #65068

Merged
merged 6 commits into from
Oct 30, 2019
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
2 changes: 2 additions & 0 deletions src/librustc/infer/error_reporting/nice_region_error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod named_anon_conflict;
mod placeholder_error;
mod outlives_closure;
mod static_impl_trait;
mod trait_impl_difference;
mod util;

impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
Expand Down Expand Up @@ -73,6 +74,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
.or_else(|| self.try_report_anon_anon_conflict())
.or_else(|| self.try_report_outlives_closure())
.or_else(|| self.try_report_static_impl_trait())
.or_else(|| self.try_report_impl_not_conforming_to_trait())
}

pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.

use syntax_pos::Span;
use crate::ty::Ty;
use crate::infer::{ValuePairs, Subtype};
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::util::common::ErrorReported;
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
if let Some(ref error) = self.error {
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
if let RegionResolutionError::SubSupConflict(
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
) = error.clone() {
match (&sup_origin, &sub_origin) {
(&Subtype(ref sup_trace), &Subtype(ref sub_trace)) => {
if let (
ValuePairs::Types(sub_expected_found),
ValuePairs::Types(sup_expected_found),
CompareImplMethodObligation { trait_item_def_id, .. },
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) {
if sup_expected_found == sub_expected_found {
self.emit_err(
var_origin.span(),
sub_expected_found.expected,
sub_expected_found.found,
self.tcx().def_span(*trait_item_def_id),
);
return Some(ErrorReported);
}
}
}
_ => {}
}
}
}
None
}

fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Span) {
let mut err = self.tcx().sess.struct_span_err(
sp,
"`impl` item signature doesn't match `trait` item signature",
);
err.note(&format!("expected `{:?}`\n found `{:?}`", expected, found));
err.span_label(sp, &format!("found {:?}", found));
err.span_label(impl_sp, &format!("expected {:?}", expected));
err.emit();
}
}
4 changes: 3 additions & 1 deletion src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore-x86
// ^ due to stderr output differences
use std::ops::Deref;
trait Trait {}

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

fn main() {}
23 changes: 9 additions & 14 deletions src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
--> $DIR/mismatched_trait_impl-2.rs:8:5
error: `impl` item signature doesn't match `trait` item signature
--> $DIR/mismatched_trait_impl-2.rs:10:5
|
LL | fn deref(&self) -> &dyn Trait {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait
|
::: $SRC_DIR/libcore/ops/deref.rs:LL:COL
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
--> $DIR/mismatched_trait_impl-2.rs:8:5
LL | fn deref(&self) -> &Self::Target;
| --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static)
|
LL | / fn deref(&self) -> &dyn Trait {
LL | | unimplemented!();
LL | | }
| |_____^
= note: ...but the lifetime must also be valid for the static lifetime...
= note: ...so that the method type is compatible with trait:
expected fn(&Struct) -> &(dyn Trait + 'static)
found fn(&Struct) -> &dyn Trait
= note: expected `fn(&Struct) -> &(dyn Trait + 'static)`
found `fn(&Struct) -> &dyn Trait`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
25 changes: 7 additions & 18 deletions src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
error: `impl` item signature doesn't match `trait` item signature
--> $DIR/mismatched_trait_impl.rs:9:5
|
LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
| ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
...
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5...
--> $DIR/mismatched_trait_impl.rs:9:5
|
LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
LL | | x
LL | | }
| |_____^
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
--> $DIR/mismatched_trait_impl.rs:9:32
|
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
| ^^
= note: ...so that the method type is compatible with trait:
expected fn(&i32, &'a u32, &u32) -> &'a u32
found fn(&i32, &u32, &u32) -> &u32
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
found `fn(&i32, &u32, &u32) -> &u32`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
2 changes: 1 addition & 1 deletion src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ trait Get {
}

impl Get for i32 {
fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR `impl` item signature doesn't match
x //~ ERROR lifetime mismatch
}
}
Expand Down
25 changes: 7 additions & 18 deletions src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
error: `impl` item signature doesn't match `trait` item signature
--> $DIR/mismatched_trait_impl.rs:9:5
|
LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
| ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
...
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5...
--> $DIR/mismatched_trait_impl.rs:9:5
|
LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
LL | | x
LL | | }
| |_____^
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
--> $DIR/mismatched_trait_impl.rs:9:32
|
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
| ^^
= note: ...so that the method type is compatible with trait:
expected fn(&i32, &'a u32, &u32) -> &'a u32
found fn(&i32, &u32, &u32) -> &u32
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
found `fn(&i32, &u32, &u32) -> &u32`

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

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0495`.
12 changes: 12 additions & 0 deletions src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
trait Foo {
fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
}

impl Foo for () {
fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
//~^ ERROR `impl` item signature doesn't match `trait` item signature
if x > y { x } else { y }
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `impl` item signature doesn't match `trait` item signature
--> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
|
LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
| ------------------------------------------- expected fn(&i32, &'a i32) -> &'a i32
...
LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32
|
= note: expected `fn(&i32, &'a i32) -> &'a i32`
found `fn(&i32, &i32) -> &i32`

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/reject-specialized-drops-8142.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
//~^ ERROR Implementations of Drop cannot be specialized

impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
//~^ ERROR cannot infer an appropriate lifetime
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw`

pub fn main() { }