From c3521fe940324447de6bc54470647aaefe54a6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 11:41:27 -0700 Subject: [PATCH 1/6] Custom lifetime error for `impl` item doesn't conform to `trait` --- .../error_reporting/nice_region_error/mod.rs | 2 + .../trait_impl_difference.rs | 53 +++++++++++++++++++ .../mismatched_trait_impl-2.rs | 2 +- .../mismatched_trait_impl-2.stderr | 17 ++---- .../mismatched_trait_impl.rs | 2 +- .../mismatched_trait_impl.stderr | 21 ++------ ...ifetime-mismatch-between-trait-and-impl.rs | 12 +++++ ...ime-mismatch-between-trait-and-impl.stderr | 11 ++++ src/test/ui/reject-specialized-drops-8142.rs | 2 +- .../ui/reject-specialized-drops-8142.stderr | 19 ++----- 10 files changed, 93 insertions(+), 48 deletions(-) create mode 100644 src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs create mode 100644 src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs create mode 100644 src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr 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 1edb1c601bf1a..cd003aa8dab70 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 0000000000000..bd5be89358939 --- /dev/null +++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -0,0 +1,53 @@ +//! Error Reporting for `impl` items that do not match the obligations from their `trait`. + +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; + +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 { + if let Some(ref error) = self.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), + ) = (&sub_trace.values, &sup_trace.values) { + if sup_expected_found == sub_expected_found { + let sp = var_origin.span(); + let mut err = self.tcx().sess.struct_span_err( + sp, + "`impl` item doesn't match `trait` item" + ); + err.note(&format!( + "expected: {:?}\n found: {:?}", + sub_expected_found.expected, + sub_expected_found.found, + )); + err.span_label(sp, &format!( + "found {:?}", + sub_expected_found.found, + )); + // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. + err.emit(); + return Some(ErrorReported); + } + } + } + _ => {} + } + } + } + None + } +} 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 d131a944721d0..3c44af7188f81 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 @@ -9,6 +9,6 @@ impl Deref for Struct { unimplemented!(); } } -//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter +//~^^^^ ERROR `impl` item doesn't match `trait` item 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 c1ec536ef4362..d3228951b2596 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,20 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements +error: `impl` item doesn't match `trait` item --> $DIR/mismatched_trait_impl-2.rs:8:5 | LL | fn deref(&self) -> &dyn Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait | -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) -> &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 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 f2ba81af9b638..a9b80a7c46fdc 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 doesn't match `trait` 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 734ca0819e416..ae65125a3dfd8 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,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements +error: `impl` item doesn't match `trait` item --> $DIR/mismatched_trait_impl.rs:9:5 | 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 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 0000000000000..cd285e70bc8f3 --- /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 doesn't match `trait` item + 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 0000000000000..099e5e97e17e0 --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -0,0 +1,11 @@ +error: `impl` item doesn't match `trait` item + --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 + | +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 f047e16bc0b94..39b959a2206c3 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -52,6 +52,6 @@ impl Drop for V { 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 `impl` item doesn't match `trait` item pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 609a40163a30c..7aa766dc50341 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -89,25 +89,14 @@ note: Use same sequence of generic type and region parameters that is on the str LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements +error: `impl` item doesn't match `trait` item --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10... - --> $DIR/reject-specialized-drops-8142.rs:17:10 - | -LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^ -note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15... - --> $DIR/reject-specialized-drops-8142.rs:17:15 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_> | -LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^ - = note: ...so that the types are compatible: - expected W<'l1, 'l2> - found W<'_, '_> + = note: expected: W<'l1, 'l2> + found: W<'_, '_> error: aborting due to 8 previous errors From ef2a8539aa4bdbcd641e51c5a85c7deb27dfae84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 20:14:48 -0700 Subject: [PATCH 2/6] review comments --- .../trait_impl_difference.rs | 27 ++++++++++--------- .../mismatched_trait_impl-2.rs | 2 +- .../mismatched_trait_impl-2.stderr | 2 +- .../mismatched_trait_impl.rs | 2 +- .../mismatched_trait_impl.stderr | 2 +- ...ifetime-mismatch-between-trait-and-impl.rs | 2 +- ...ime-mismatch-between-trait-and-impl.stderr | 2 +- src/test/ui/reject-specialized-drops-8142.rs | 2 +- .../ui/reject-specialized-drops-8142.stderr | 2 +- 9 files changed, 23 insertions(+), 20 deletions(-) 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 index bd5be89358939..f546acdb87859 100644 --- 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 @@ -1,5 +1,7 @@ //! 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; @@ -25,21 +27,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = (&sub_trace.values, &sup_trace.values) { if sup_expected_found == sub_expected_found { let sp = var_origin.span(); - let mut err = self.tcx().sess.struct_span_err( + self.emit_err( sp, - "`impl` item doesn't match `trait` item" - ); - err.note(&format!( - "expected: {:?}\n found: {:?}", sub_expected_found.expected, sub_expected_found.found, - )); - err.span_label(sp, &format!( - "found {:?}", - sub_expected_found.found, - )); - // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. - err.emit(); + ); return Some(ErrorReported); } } @@ -50,4 +42,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } None } + + fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>) { + 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)); + // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. + 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 3c44af7188f81..60e1585a51a80 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 @@ -9,6 +9,6 @@ impl Deref for Struct { unimplemented!(); } } -//~^^^^ ERROR `impl` item doesn't match `trait` item +//~^^^^ ERROR `impl` item signature doesn't match `trait` item signature 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 d3228951b2596..ea88cb14f0118 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,4 +1,4 @@ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl-2.rs:8:5 | LL | fn deref(&self) -> &dyn Trait { 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 a9b80a7c46fdc..b9e02e967c126 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 `impl` item doesn't match `trait` + 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 ae65125a3dfd8..4b0af292bbc24 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -1,4 +1,4 @@ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { 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 index cd285e70bc8f3..2ce1a0f454651 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs @@ -4,7 +4,7 @@ trait Foo { impl Foo for () { fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - //~^ ERROR `impl` item doesn't match `trait` item + //~^ ERROR `impl` item signature doesn't match `trait` item signature if x > y { x } else { y } } } 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 index 099e5e97e17e0..cdb4c16eca35b 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -1,4 +1,4 @@ -error: `impl` item doesn't match `trait` item +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: &'a i32, y: &'a i32) -> &'a i32 { diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index 39b959a2206c3..621626f3a0d91 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -52,6 +52,6 @@ impl Drop for V { 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 `impl` item doesn't match `trait` item +//~^ ERROR `impl` item signature doesn't match `trait` item signature pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 7aa766dc50341..bc7604cdede57 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -89,7 +89,7 @@ note: Use same sequence of generic type and region parameters that is on the str LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT From 6998085c030d657d7c8698585409c0fe878d5e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 10:36:26 -0700 Subject: [PATCH 3/6] Point at the trait item and tweak wording --- .../nice_region_error/trait_impl_difference.rs | 18 +++++++++++++++--- .../mismatched_trait_impl-2.rs | 2 +- .../mismatched_trait_impl-2.stderr | 10 +++++++--- .../mismatched_trait_impl.stderr | 8 +++++--- ...time-mismatch-between-trait-and-impl.stderr | 7 +++++-- .../ui/reject-specialized-drops-8142.stderr | 6 +++--- 6 files changed, 36 insertions(+), 15 deletions(-) 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 index f546acdb87859..565ba6b33b8c0 100644 --- 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 @@ -6,11 +6,13 @@ 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 { if let Some(ref error) = self.error { + debug!("try_report_impl_not_conforming_to_trait {:?}", error); if let RegionResolutionError::SubSupConflict( _, var_origin, @@ -27,10 +29,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = (&sub_trace.values, &sup_trace.values) { if sup_expected_found == sub_expected_found { let sp = var_origin.span(); + let impl_sp = if let CompareImplMethodObligation { + trait_item_def_id, .. + } = &sub_trace.cause.code { + Some(self.tcx().def_span(*trait_item_def_id)) + } else { + None + }; self.emit_err( sp, sub_expected_found.expected, sub_expected_found.found, + impl_sp, ); return Some(ErrorReported); } @@ -43,14 +53,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None } - fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>) { + fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Option) { 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.note(&format!("expected `{:?}`\n found `{:?}`", expected, found)); err.span_label(sp, &format!("found {:?}", found)); - // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. + if let Some(span) = impl_sp { + err.span_label(span, &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 60e1585a51a80..1b524ec3833e8 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 @@ -6,9 +6,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 `impl` item signature doesn't match `trait` item signature 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 ea88cb14f0118..c1c4ec9ed7b92 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 @@ -3,10 +3,14 @@ error: `impl` item signature doesn't match `trait` item signature | LL | fn deref(&self) -> &dyn Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait + | + ::: $SRC_DIR/libcore/ops/deref.rs:LL:COL | - = note: expected: fn(&Struct) -> &(dyn Trait + 'static) - found: fn(&Struct) -> &dyn Trait +LL | fn deref(&self) -> &Self::Target; + | --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static) + | + = 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.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 4b0af292bbc24..bc302e91c1c51 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -1,11 +1,14 @@ 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: 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 @@ -19,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.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index cdb4c16eca35b..d07f305954b6e 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -1,11 +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 + = 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.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index bc7604cdede57..887edc7299375 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -95,10 +95,10 @@ error: `impl` item signature doesn't match `trait` item signature LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_> | - = note: expected: W<'l1, 'l2> - found: W<'_, '_> + = note: expected `W<'l1, 'l2>` + found `W<'_, '_>` error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0366, E0367, E0495. +Some errors have detailed explanations: E0308, E0366, E0367. For more information about an error, try `rustc --explain E0308`. From 9ae0c1d7e9dc18a06b1280561e539175da189b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 10:47:48 -0700 Subject: [PATCH 4/6] Make error apply only to impl/trait mismatch --- .../trait_impl_difference.rs | 21 ++++++------------- src/test/ui/reject-specialized-drops-8142.rs | 2 +- .../ui/reject-specialized-drops-8142.stderr | 21 ++++++++++++++----- 3 files changed, 23 insertions(+), 21 deletions(-) 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 index 565ba6b33b8c0..0194300c50721 100644 --- 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 @@ -26,21 +26,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let ( ValuePairs::Types(sub_expected_found), ValuePairs::Types(sup_expected_found), - ) = (&sub_trace.values, &sup_trace.values) { + CompareImplMethodObligation { trait_item_def_id, .. }, + ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) { if sup_expected_found == sub_expected_found { - let sp = var_origin.span(); - let impl_sp = if let CompareImplMethodObligation { - trait_item_def_id, .. - } = &sub_trace.cause.code { - Some(self.tcx().def_span(*trait_item_def_id)) - } else { - None - }; self.emit_err( - sp, + var_origin.span(), sub_expected_found.expected, sub_expected_found.found, - impl_sp, + self.tcx().def_span(*trait_item_def_id), ); return Some(ErrorReported); } @@ -53,16 +46,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None } - fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Option) { + 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)); - if let Some(span) = impl_sp { - err.span_label(span, &format!("expected {:?}", expected)); - } + err.span_label(impl_sp, &format!("expected {:?}", expected)); err.emit(); } } diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index 621626f3a0d91..b3cb83f94e053 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -52,6 +52,6 @@ impl Drop for V { 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 `impl` item signature doesn't match `trait` item signature +//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 887edc7299375..609a40163a30c 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -89,16 +89,27 @@ note: Use same sequence of generic type and region parameters that is on the str LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `impl` item signature doesn't match `trait` item signature +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10... + --> $DIR/reject-specialized-drops-8142.rs:17:10 + | +LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^ +note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15... + --> $DIR/reject-specialized-drops-8142.rs:17:15 | - = note: expected `W<'l1, 'l2>` - found `W<'_, '_>` +LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^ + = note: ...so that the types are compatible: + expected W<'l1, 'l2> + found W<'_, '_> error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0366, E0367. +Some errors have detailed explanations: E0308, E0366, E0367, E0495. For more information about an error, try `rustc --explain E0308`. From a3b86879a09d71755025770038ccc6675cb10c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 10:57:52 -0700 Subject: [PATCH 5/6] Fix NLL test --- .../mismatched_trait_impl.nll.stderr | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) 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 b5287f32a5045..c245d78ae828f 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`. From 213fd1f37f272e352ceb7dcdaddcd90b1da54d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 29 Oct 2019 10:19:40 -0700 Subject: [PATCH 6/6] Silence crate external span error in x86 platforms This causes issues in at least `dist-i586-gnu-i586-i686-musl`, possibly others. --- src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs | 2 ++ src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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 1b524ec3833e8..eca9a67fcb387 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 {} 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 c1c4ec9ed7b92..d3862e3d4df60 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,5 +1,5 @@ error: `impl` item signature doesn't match `trait` item signature - --> $DIR/mismatched_trait_impl-2.rs:8:5 + --> $DIR/mismatched_trait_impl-2.rs:10:5 | LL | fn deref(&self) -> &dyn Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait