diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 74ded948b18..d4544dadaeb 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -102,6 +102,7 @@ use self::Ordering::*; /// ``` #[lang = "eq"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"] pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used /// by `==`. @@ -550,6 +551,7 @@ impl PartialOrd for Ordering { /// ``` #[lang = "ord"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"] pub trait PartialOrd: PartialEq { /// This method returns an ordering between `self` and `other` values if one exists. /// diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index d203b68c0df..175b3a5a69a 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -242,6 +242,7 @@ pub trait Drop { /// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"] pub trait Add { /// The resulting type after applying the `+` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -315,6 +316,7 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html #[lang = "sub"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"] pub trait Sub { /// The resulting type after applying the `-` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -437,6 +439,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "mul"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"] pub trait Mul { /// The resulting type after applying the `*` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -565,6 +568,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "div"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"] pub trait Div { /// The resulting type after applying the `/` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -644,6 +648,7 @@ div_impl_float! { f32 f64 } /// ``` #[lang = "rem"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] pub trait Rem { /// The resulting type after applying the `%` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -883,6 +888,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "bitand"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] pub trait BitAnd { /// The resulting type after applying the `&` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -966,6 +972,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "bitor"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] pub trait BitOr { /// The resulting type after applying the `|` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -1052,6 +1059,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "bitxor"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] pub trait BitXor { /// The resulting type after applying the `^` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -1134,6 +1142,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "shl"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] pub trait Shl { /// The resulting type after applying the `<<` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -1237,6 +1246,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } /// ``` #[lang = "shr"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] pub trait Shr { /// The resulting type after applying the `>>` operator #[stable(feature = "rust1", since = "1.0.0")] @@ -1321,6 +1331,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// ``` #[lang = "add_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"] pub trait AddAssign { /// The method for the `+=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1377,6 +1388,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "sub_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"] pub trait SubAssign { /// The method for the `-=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1422,6 +1434,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "mul_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"] pub trait MulAssign { /// The method for the `*=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1467,6 +1480,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "div_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"] pub trait DivAssign { /// The method for the `/=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1511,6 +1525,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "rem_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"] pub trait RemAssign { /// The method for the `%=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1597,6 +1612,7 @@ rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "bitand_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] pub trait BitAndAssign { /// The method for the `&=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1641,6 +1657,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "bitor_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] pub trait BitOrAssign { /// The method for the `|=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1685,6 +1702,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "bitxor_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] pub trait BitXorAssign { /// The method for the `^=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1729,6 +1747,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// ``` #[lang = "shl_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] pub trait ShlAssign { /// The method for the `<<=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] @@ -1794,6 +1813,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// ``` #[lang = "shr_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] pub trait ShrAssign { /// The method for the `>>=` operator #[stable(feature = "op_assign_traits", since = "1.8.0")] diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 152dd6ac300..931c77badad 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -524,15 +524,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "the trait bound `{}` is not satisfied{}", trait_ref.to_predicate(), post_message); - 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) { // If a where-clause may be useful, remind the @@ -544,17 +537,21 @@ 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) { + } 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 { - // If we can't show anything useful, try to find - // similar impls. + // 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 } @@ -997,3 +994,4 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { suggested_limit)); } } + diff --git a/src/test/compile-fail/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs similarity index 95% rename from src/test/compile-fail/impl-trait/equality.rs rename to src/test/ui/impl-trait/equality.rs index 36df4f0eb4d..96db53ad2e4 100644 --- a/src/test/compile-fail/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -32,7 +32,7 @@ fn sum_to(n: u32) -> impl Foo { 0 } else { n + sum_to(n - 1) - //~^ ERROR the trait bound `u32: std::ops::Add` is not satisfied + //~^ ERROR no implementation for `u32 + impl Foo` } } diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr new file mode 100644 index 00000000000..bd024d6766e --- /dev/null +++ b/src/test/ui/impl-trait/equality.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/equality.rs:25:5 + | +25 | 0_u32 + | ^^^^^ expected i32, found u32 + | + = note: expected type `i32` + found type `u32` + +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` + | + = note: no implementation for `u32 + impl Foo` + +error[E0308]: mismatched types + --> $DIR/equality.rs:53:18 + | +53 | let _: u32 = hide(0_u32); + | ^^^^^^^^^^^ expected u32, found anonymized type + | + = note: expected type `u32` + found type `impl Foo` + +error[E0308]: mismatched types + --> $DIR/equality.rs:59:18 + | +59 | let _: i32 = Leak::leak(hide(0_i32)); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found associated type + | + = note: expected type `i32` + found type `::T` + +error[E0308]: mismatched types + --> $DIR/equality.rs:66:10 + | +66 | x = (x.1, + | ^^^ expected u32, found i32 + | + = note: expected type `impl Foo` (u32) + found type `impl Foo` (i32) + +error[E0308]: mismatched types + --> $DIR/equality.rs:69:10 + | +69 | x.0); + | ^^^ expected i32, found u32 + | + = note: expected type `impl Foo` (i32) + found type `impl Foo` (u32) + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/mismatched_types/binops.rs b/src/test/ui/mismatched_types/binops.rs new file mode 100644 index 00000000000..98449e59664 --- /dev/null +++ b/src/test/ui/mismatched_types/binops.rs @@ -0,0 +1,18 @@ +// 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 main() { + 1 + Some(1); + 2 as usize - Some(1); + 3 * (); + 4 / ""; + 5 < String::new(); + 6 == Ok(1); +} diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr new file mode 100644 index 00000000000..a0f7ff65870 --- /dev/null +++ b/src/test/ui/mismatched_types/binops.stderr @@ -0,0 +1,58 @@ +error[E0277]: the trait bound `{integer}: std::ops::Add>` is not satisfied + --> $DIR/binops.rs:12:5 + | +12 | 1 + Some(1); + | ^^^^^^^^^^^ the trait `std::ops::Add>` is not implemented for `{integer}` + | + = note: no implementation for `{integer} + std::option::Option<{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` + | + = note: no implementation for `usize - std::option::Option<{integer}>` + +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}` + | + = note: no implementation 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}` + | + = note: no implementation for `{integer} / &str` + +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}` + | + = note: can't compare `{integer}` with `std::string::String` + +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}` + | + = note: can't compare `{integer}` with `std::string::String` + +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}` + | + = note: can't compare `{integer}` with `std::result::Result<{integer}, _>` + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 85c11c05b9f..161b6ca48b2 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -9,11 +9,7 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied 27 | | y), | |______________^ ...ending here: the trait `std::ops::Add<()>` is not implemented for `u32` | - = help: the following implementations were found: - - <&'a u32 as std::ops::Add> - > - <&'b u32 as std::ops::Add<&'a u32>> + = note: no implementation for `u32 + ()` error: aborting due to previous error