about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-10-30 02:20:55 +0000
committerbors <bors@rust-lang.org>2019-10-30 02:20:55 +0000
commit0b7e28a1610924a27471ffdb59a2885709b3b415 (patch)
tree6cbaf618f4e15a4f740a4120843f33f730bbb323
parentaa69777ea2902208b24b3fd77767d577ceaf6386 (diff)
parent213fd1f37f272e352ceb7dcdaddcd90b1da54d61 (diff)
downloadrust-0b7e28a1610924a27471ffdb59a2885709b3b415.tar.gz
rust-0b7e28a1610924a27471ffdb59a2885709b3b415.zip
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.
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs59
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs4
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr23
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr25
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs2
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr25
-rw-r--r--src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs12
-rw-r--r--src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr14
-rw-r--r--src/test/ui/reject-specialized-drops-8142.rs2
10 files changed, 115 insertions, 53 deletions
diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
index 1edb1c601bf..cd003aa8dab 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
@@ -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> {
@@ -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>) {
diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs
new file mode 100644
index 00000000000..0194300c507
--- /dev/null
+++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -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();
+    }
+}
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
index d131a944721..eca9a67fcb3 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
@@ -1,3 +1,5 @@
+// ignore-x86
+// ^ due to stderr output differences
 use std::ops::Deref;
 trait Trait {}
 
@@ -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() {}
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
index c1ec536ef43..d3862e3d4df 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
@@ -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`.
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
index b5287f32a50..c245d78ae82 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
@@ -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`.
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
index f2ba81af9b6..b9e02e967c1 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs
@@ -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
     }
 }
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
index 734ca0819e4..bc302e91c1c 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
@@ -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
@@ -32,4 +22,3 @@ LL |         x
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs
new file mode 100644
index 00000000000..2ce1a0f4546
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs
@@ -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() {}
diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
new file mode 100644
index 00000000000..d07f305954b
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
@@ -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
+
diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs
index f047e16bc0b..b3cb83f94e0 100644
--- a/src/test/ui/reject-specialized-drops-8142.rs
+++ b/src/test/ui/reject-specialized-drops-8142.rs
@@ -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() { }