From 747287a2b3b6649d59cfd11be1fb32e667f71a3f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 26 Apr 2017 18:42:27 +0200 Subject: [PATCH] Add better error message when == operator is badly used --- src/librustc/traits/error_reporting.rs | 28 ++++++++++++------- src/test/compile-fail/E0277-2.rs | 1 - src/test/compile-fail/E0277.rs | 1 - src/test/compile-fail/const-unsized.rs | 4 --- .../impl-trait/auto-trait-leak.rs | 2 -- .../on-unimplemented/multiple-impls.rs | 3 -- .../compile-fail/on-unimplemented/on-impl.rs | 1 - .../compile-fail/on-unimplemented/on-trait.rs | 3 +- .../on-unimplemented/slice-index.rs | 2 -- src/test/compile-fail/partialeq_help.rs | 20 +++++++++++++ .../trait-suggest-where-clause.rs | 16 ++++++----- src/test/ui/impl-trait/equality.stderr | 4 +-- src/test/ui/mismatched_types/binops.stderr | 28 +++++++++---------- .../ui/mismatched_types/cast-rfc0401.stderr | 8 +++--- src/test/ui/resolve/issue-5035-2.stderr | 4 +-- src/test/ui/span/multiline-span-simple.stderr | 4 +-- 16 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 src/test/compile-fail/partialeq_help.rs diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 152e3353994..3c7761c6cd3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -559,6 +559,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { trait_ref.to_predicate(), post_message); + let unimplemented_note = self.on_unimplemented_note(trait_ref, obligation); + if let Some(ref s) = unimplemented_note { + // If it has a custom "#[rustc_on_unimplemented]" + // error message, let's display it as the label! + err.span_label(span, s.as_str()); + err.help(&format!("{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); + } else { + err.span_label(span, + &*format!("{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); + } + // Try to report a help message if !trait_ref.has_infer_types() && self.predicate_can_apply(trait_ref) { @@ -571,21 +588,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // which is somewhat confusing. err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); - } else if let Some(s) = self.on_unimplemented_note(trait_ref, obligation) { - // If it has a custom "#[rustc_on_unimplemented]" - // error message, let's display it! - err.note(&s); - } else { + } else if unimplemented_note.is_none() { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_ref); self.report_similar_impl_candidates(impl_candidates, &mut err); } - err.span_label(span, - format!("{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty())); err } diff --git a/src/test/compile-fail/E0277-2.rs b/src/test/compile-fail/E0277-2.rs index 211c0e6f890..816d3529554 100644 --- a/src/test/compile-fail/E0277-2.rs +++ b/src/test/compile-fail/E0277-2.rs @@ -25,7 +25,6 @@ fn is_send() { } fn main() { is_send::(); //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo` - //~| NOTE within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8` //~| NOTE: `*const u8` cannot be sent between threads safely //~| NOTE: required because it appears within the type `Baz` //~| NOTE: required because it appears within the type `Bar` diff --git a/src/test/compile-fail/E0277.rs b/src/test/compile-fail/E0277.rs index e31fea1e458..8b34936419d 100644 --- a/src/test/compile-fail/E0277.rs +++ b/src/test/compile-fail/E0277.rs @@ -20,7 +20,6 @@ fn some_func(foo: T) { fn f(p: Path) { } //~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path` -//~| NOTE within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]` //~| NOTE `[u8]` does not have a constant size known at compile-time //~| NOTE required because it appears within the type `std::path::Path` //~| NOTE all local variables must have a statically known size diff --git a/src/test/compile-fail/const-unsized.rs b/src/test/compile-fail/const-unsized.rs index 23cff4ac6ad..4b212814ded 100644 --- a/src/test/compile-fail/const-unsized.rs +++ b/src/test/compile-fail/const-unsized.rs @@ -12,25 +12,21 @@ use std::fmt::Debug; const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync)); //~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size const CONST_FOO: str = *"foo"; //~^ ERROR `str: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `str` //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync)); //~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size static STATIC_BAR: str = *"bar"; //~^ ERROR `str: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `str` //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size diff --git a/src/test/compile-fail/impl-trait/auto-trait-leak.rs b/src/test/compile-fail/impl-trait/auto-trait-leak.rs index 13e53cab172..8a5033e7647 100644 --- a/src/test/compile-fail/impl-trait/auto-trait-leak.rs +++ b/src/test/compile-fail/impl-trait/auto-trait-leak.rs @@ -26,7 +26,6 @@ fn send(_: T) {} fn main() { send(before()); //~^ ERROR the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied - //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc>` //~| NOTE `std::rc::Rc>` cannot be sent between threads safely //~| NOTE required because it appears within the type `[closure //~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>` @@ -34,7 +33,6 @@ fn main() { send(after()); //~^ ERROR the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied - //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc>` //~| NOTE `std::rc::Rc>` cannot be sent between threads safely //~| NOTE required because it appears within the type `[closure //~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>` diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/compile-fail/on-unimplemented/multiple-impls.rs index 0ad9f21e098..0df8c41ffe1 100644 --- a/src/test/compile-fail/on-unimplemented/multiple-impls.rs +++ b/src/test/compile-fail/on-unimplemented/multiple-impls.rs @@ -42,17 +42,14 @@ impl Index> for [i32] { fn main() { Index::index(&[] as &[i32], 2u32); //~^ ERROR E0277 - //~| NOTE the trait `Index` is not implemented for `[i32]` //~| NOTE trait message //~| NOTE required by Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 - //~| NOTE the trait `Index>` is not implemented for `[i32]` //~| NOTE on impl for Foo //~| NOTE required by Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 - //~| NOTE the trait `Index>` is not implemented for `[i32]` //~| NOTE on impl for Bar //~| NOTE required by } diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/compile-fail/on-unimplemented/on-impl.rs index a7c599330a0..79021cd03cc 100644 --- a/src/test/compile-fail/on-unimplemented/on-impl.rs +++ b/src/test/compile-fail/on-unimplemented/on-impl.rs @@ -31,7 +31,6 @@ impl Index for [i32] { fn main() { Index::::index(&[1, 2, 3] as &[i32], 2u32); //~^ ERROR E0277 - //~| NOTE the trait `Index` is not implemented for `[i32]` //~| NOTE a usize is required //~| NOTE required by } diff --git a/src/test/compile-fail/on-unimplemented/on-trait.rs b/src/test/compile-fail/on-unimplemented/on-trait.rs index 0f4b0919b65..a8daef356a5 100644 --- a/src/test/compile-fail/on-unimplemented/on-trait.rs +++ b/src/test/compile-fail/on-unimplemented/on-trait.rs @@ -35,9 +35,8 @@ pub fn main() { //~^ ERROR //~^^ NOTE a collection of type `std::option::Option>` cannot be built from an iterator over elements of type `&u8` //~^^^ NOTE required by `collect` - //~| NOTE the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option>` + let x: String = foobar(); //~ ERROR //~^ NOTE test error `std::string::String` with `u8` `_` `u32` //~^^ NOTE required by `foobar` - //~| NOTE the trait `Foo` is not implemented for `std::string::String` } diff --git a/src/test/compile-fail/on-unimplemented/slice-index.rs b/src/test/compile-fail/on-unimplemented/slice-index.rs index 1a9ed2dd6e4..5d30c2e982e 100644 --- a/src/test/compile-fail/on-unimplemented/slice-index.rs +++ b/src/test/compile-fail/on-unimplemented/slice-index.rs @@ -20,10 +20,8 @@ fn main() { let x = &[1, 2, 3] as &[i32]; x[1i32]; //~ ERROR E0277 //~| NOTE slice indices are of type `usize` or ranges of `usize` - //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32` //~| NOTE required because of the requirements on the impl of `std::ops::Index` x[..1i32]; //~ ERROR E0277 //~| NOTE slice indices are of type `usize` or ranges of `usize` - //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo` //~| NOTE requirements on the impl of `std::ops::Index>` } diff --git a/src/test/compile-fail/partialeq_help.rs b/src/test/compile-fail/partialeq_help.rs new file mode 100644 index 00000000000..52c24473bd3 --- /dev/null +++ b/src/test/compile-fail/partialeq_help.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(a: &T, b: T) { + a == b; //~ ERROR E0277 + //~| NOTE can't compare `&T` with `T` + //~| HELP the trait `std::cmp::PartialEq` is not implemented for `&T` + //~| HELP consider adding a `where &T: std::cmp::PartialEq` bound +} + +fn main() { + foo(&1, 1); +} diff --git a/src/test/compile-fail/trait-suggest-where-clause.rs b/src/test/compile-fail/trait-suggest-where-clause.rs index 7530d8890b9..2c38d8d2e28 100644 --- a/src/test/compile-fail/trait-suggest-where-clause.rs +++ b/src/test/compile-fail/trait-suggest-where-clause.rs @@ -16,51 +16,53 @@ fn check() { // suggest a where-clause, if needed mem::size_of::(); //~^ ERROR `U: std::marker::Sized` is not satisfied - //~| NOTE the trait `std::marker::Sized` is not implemented for `U` //~| HELP consider adding a `where U: std::marker::Sized` bound //~| NOTE required by `std::mem::size_of` + //~| NOTE `U` does not have a constant size known at compile-time + //~| HELP the trait `std::marker::Sized` is not implemented for `U` mem::size_of::>(); //~^ ERROR `U: std::marker::Sized` is not satisfied - //~| NOTE the trait `std::marker::Sized` is not implemented for `U` //~| HELP consider adding a `where U: std::marker::Sized` bound //~| NOTE required because it appears within the type `Misc` //~| NOTE required by `std::mem::size_of` + //~| NOTE `U` does not have a constant size known at compile-time + //~| HELP within `Misc`, the trait `std::marker::Sized` is not implemented for `U` // ... even if T occurs as a type parameter >::from; //~^ ERROR `u64: std::convert::From` is not satisfied - //~| NOTE the trait `std::convert::From` is not implemented for `u64` //~| HELP consider adding a `where u64: std::convert::From` bound //~| NOTE required by `std::convert::From::from` + //~| NOTE the trait `std::convert::From` is not implemented for `u64` ::Item>>::from; //~^ ERROR `u64: std::convert::From<::Item>` is not satisfied - //~| NOTE the trait `std::convert::From<::Item>` is not implemented //~| HELP consider adding a `where u64: //~| NOTE required by `std::convert::From::from` + //~| NOTE the trait `std::convert::From<::Item>` is not implemented // ... but not if there are inference variables as From>::from; //~^ ERROR `Misc<_>: std::convert::From` is not satisfied - //~| NOTE the trait `std::convert::From` is not implemented for `Misc<_>` //~| NOTE required by `std::convert::From::from` + //~| NOTE the trait `std::convert::From` is not implemented for `Misc<_>` // ... and also not if the error is not related to the type mem::size_of::<[T]>(); //~^ ERROR `[T]: std::marker::Sized` is not satisfied - //~| NOTE the trait `std::marker::Sized` is not implemented for `[T]` //~| NOTE `[T]` does not have a constant size //~| NOTE required by `std::mem::size_of` + //~| HELP the trait `std::marker::Sized` is not implemented for `[T]` mem::size_of::<[&U]>(); //~^ ERROR `[&U]: std::marker::Sized` is not satisfied - //~| NOTE the trait `std::marker::Sized` is not implemented for `[&U]` //~| NOTE `[&U]` does not have a constant size //~| NOTE required by `std::mem::size_of` + //~| HELP the trait `std::marker::Sized` is not implemented for `[&U]` } fn main() { diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index bd024d6766e..08d9043f65e 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -11,9 +11,9 @@ error[E0277]: the trait bound `u32: std::ops::Add` is not satisfied --> $DIR/equality.rs:34:9 | 34 | n + sum_to(n - 1) - | ^^^^^^^^^^^^^^^^^ the trait `std::ops::Add` is not implemented for `u32` + | ^^^^^^^^^^^^^^^^^ no implementation for `u32 + impl Foo` | - = note: no implementation for `u32 + impl Foo` + = help: the trait `std::ops::Add` is not implemented for `u32` error[E0308]: mismatched types --> $DIR/equality.rs:53:18 diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index a0f7ff65870..773bf0593c5 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -2,57 +2,57 @@ error[E0277]: the trait bound `{integer}: std::ops::Add $DIR/binops.rs:12:5 | 12 | 1 + Some(1); - | ^^^^^^^^^^^ the trait `std::ops::Add>` is not implemented for `{integer}` + | ^^^^^^^^^^^ no implementation for `{integer} + std::option::Option<{integer}>` | - = note: no implementation for `{integer} + std::option::Option<{integer}>` + = help: the trait `std::ops::Add>` is not implemented for `{integer}` error[E0277]: the trait bound `usize: std::ops::Sub>` is not satisfied --> $DIR/binops.rs:13:5 | 13 | 2 as usize - Some(1); - | ^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Sub>` is not implemented for `usize` + | ^^^^^^^^^^^^^^^^^^^^ no implementation for `usize - std::option::Option<{integer}>` | - = note: no implementation for `usize - std::option::Option<{integer}>` + = help: the trait `std::ops::Sub>` is not implemented for `usize` error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied --> $DIR/binops.rs:14:5 | 14 | 3 * (); - | ^^^^^^ the trait `std::ops::Mul<()>` is not implemented for `{integer}` + | ^^^^^^ no implementation for `{integer} * ()` | - = note: no implementation for `{integer} * ()` + = help: the trait `std::ops::Mul<()>` is not implemented for `{integer}` error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied --> $DIR/binops.rs:15:5 | 15 | 4 / ""; - | ^^^^^^ the trait `std::ops::Div<&str>` is not implemented for `{integer}` + | ^^^^^^ no implementation for `{integer} / &str` | - = note: no implementation for `{integer} / &str` + = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}` error[E0277]: the trait bound `{integer}: std::cmp::PartialEq` is not satisfied --> $DIR/binops.rs:16:5 | 16 | 5 < String::new(); - | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialEq` is not implemented for `{integer}` + | ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String` | - = note: can't compare `{integer}` with `std::string::String` + = help: the trait `std::cmp::PartialEq` is not implemented for `{integer}` error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd` is not satisfied --> $DIR/binops.rs:16:5 | 16 | 5 < String::new(); - | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialOrd` is not implemented for `{integer}` + | ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String` | - = note: can't compare `{integer}` with `std::string::String` + = help: the trait `std::cmp::PartialOrd` is not implemented for `{integer}` error[E0277]: the trait bound `{integer}: std::cmp::PartialEq>` is not satisfied --> $DIR/binops.rs:17:5 | 17 | 6 == Ok(1); - | ^^^^^^^^^^ the trait `std::cmp::PartialEq>` is not implemented for `{integer}` + | ^^^^^^^^^^ can't compare `{integer}` with `std::result::Result<{integer}, _>` | - = note: can't compare `{integer}` with `std::result::Result<{integer}, _>` + = help: the trait `std::cmp::PartialEq>` is not implemented for `{integer}` error: aborting due to 7 previous errors diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 7fd10f3cb68..8853b35eb8b 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -210,18 +210,18 @@ error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied --> $DIR/cast-rfc0401.rs:63:13 | 63 | let _ = fat_v as *const Foo; - | ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]` + | ^^^^^ `[u8]` does not have a constant size known at compile-time | - = note: `[u8]` does not have a constant size known at compile-time + = help: the trait `std::marker::Sized` is not implemented for `[u8]` = note: required for the cast to the object type `Foo` error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied --> $DIR/cast-rfc0401.rs:72:13 | 72 | let _ = a as *const Foo; - | ^ the trait `std::marker::Sized` is not implemented for `str` + | ^ `str` does not have a constant size known at compile-time | - = note: `str` does not have a constant size known at compile-time + = help: the trait `std::marker::Sized` is not implemented for `str` = note: required for the cast to the object type `Foo` error: casting `&{float}` as `f32` is invalid diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index 72b1578e0d0..791b20725f3 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied --> $DIR/issue-5035-2.rs:14:8 | 14 | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied - | ^^ the trait `std::marker::Sized` is not implemented for `I + 'static` + | ^^ `I + 'static` does not have a constant size known at compile-time | - = note: `I + 'static` does not have a constant size known at compile-time + = help: the trait `std::marker::Sized` is not implemented for `I + 'static` = note: all local variables must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 843c1e811d5..44d5379648d 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -7,9 +7,9 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied 25 | | bar(x, 26 | | 27 | | y), - | |______________^ the trait `std::ops::Add<()>` is not implemented for `u32` + | |______________^ no implementation for `u32 + ()` | - = note: no implementation for `u32 + ()` + = help: the trait `std::ops::Add<()>` is not implemented for `u32` error: aborting due to previous error