]> git.lizzy.rs Git - rust.git/commitdiff
should_impl_trait - pr comments
authorTim Nielens <tim.nielens@gmail.com>
Wed, 29 Jul 2020 23:41:12 +0000 (01:41 +0200)
committerTim Nielens <tim.nielens@gmail.com>
Sun, 9 Aug 2020 13:10:00 +0000 (15:10 +0200)
clippy_lints/src/methods/mod.rs
tests/ui/methods.rs
tests/ui/methods.stderr
tests/ui/should_impl_trait/corner_cases.rs [new file with mode: 0644]
tests/ui/should_impl_trait/method_list_1.rs [new file with mode: 0644]
tests/ui/should_impl_trait/method_list_1.stderr [new file with mode: 0644]
tests/ui/should_impl_trait/method_list_2.rs [new file with mode: 0644]
tests/ui/should_impl_trait/method_list_2.stderr [new file with mode: 0644]

index bad1bb7224eb05c6ac9a16f148733fbd0b39cf06..a549c3b78ef6a4ab5d5cea14baf078a38705f8d3 100644 (file)
@@ -1495,25 +1495,31 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
 
             then {
                 if cx.access_levels.is_exported(impl_item.hir_id) {
-                // check missing trait implementations
-                    for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS {
-                        let no_lifetime_params = || {
-                            !impl_item.generics.params.iter()
-                                .any(|p| matches!(
-                                    p.kind,
-                                    hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }))
-                        };
-                        if name == method_name &&
-                            sig.decl.inputs.len() == n_args &&
-                            out_type.matches(cx, &sig.decl.output) &&
-                            self_kind.matches(cx, self_ty, first_arg_ty) &&
-                            fn_header_equals(*fn_header, sig.header) &&
-                            // ignore methods with lifetime params, risk of false positive
-                            no_lifetime_params()
+                    // check missing trait implementations
+                    for method_config in &TRAIT_METHODS {
+                        if name == method_config.method_name &&
+                            sig.decl.inputs.len() == method_config.param_count &&
+                            method_config.output_type.matches(cx, &sig.decl.output) &&
+                            method_config.self_kind.matches(cx, self_ty, first_arg_ty) &&
+                            fn_header_equals(*method_config.fn_header, sig.header) &&
+                            method_config.lifetime_param_cond(&impl_item)
                         {
-                            span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!(
-                                "defining a method called `{}` on this type; consider implementing \
-                                the `{}` trait or choosing a less ambiguous name", name, trait_name));
+                            span_lint_and_help(
+                                cx,
+                                SHOULD_IMPLEMENT_TRAIT,
+                                impl_item.span,
+                                &format!(
+                                    "method `{}` can be confused for the standard trait method `{}::{}`",
+                                    method_config.method_name,
+                                    method_config.trait_name,
+                                    method_config.method_name
+                                ),
+                                None,
+                                &format!(
+                                    "consider implementing the trait `{}` or choosing a less ambiguous method name",
+                                    method_config.trait_name
+                                )
+                            );
                         }
                     }
                 }
@@ -3412,39 +3418,85 @@ enum Convention {
     abi: rustc_target::spec::abi::Abi::Rust,
 };
 
+struct ShouldImplTraitCase {
+    trait_name: &'static str,
+    method_name: &'static str,
+    param_count: usize,
+    fn_header: &'static hir::FnHeader,
+    // implicit self kind expected (none, self, &self, ...)
+    self_kind: SelfKind,
+    // checks against the output type
+    output_type: OutType,
+    // certain methods with explicit lifetimes can't implement the equivalent trait method
+    lint_explicit_lifetime: bool,
+}
+impl ShouldImplTraitCase {
+    const fn new(
+        trait_name: &'static str,
+        method_name: &'static str,
+        param_count: usize,
+        fn_header: &'static hir::FnHeader,
+        self_kind: SelfKind,
+        output_type: OutType,
+        lint_explicit_lifetime: bool,
+    ) -> ShouldImplTraitCase {
+        ShouldImplTraitCase {
+            trait_name,
+            method_name,
+            param_count,
+            fn_header,
+            self_kind,
+            output_type,
+            lint_explicit_lifetime,
+        }
+    }
+
+    fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
+        self.lint_explicit_lifetime
+            || !impl_item.generics.params.iter().any(|p| {
+                matches!(
+                    p.kind,
+                    hir::GenericParamKind::Lifetime {
+                        kind: hir::LifetimeParamKind::Explicit
+                    }
+                )
+            })
+    }
+}
+
 #[rustfmt::skip]
-const TRAIT_METHODS: [(&str, usize, &hir::FnHeader, SelfKind, OutType, &str); 30] = [
-    ("add", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Add"),
-    ("as_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"),
-    ("as_ref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"),
-    ("bitand", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitAnd"),
-    ("bitor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitOr"),
-    ("bitxor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitXor"),
-    ("borrow", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"),
-    ("borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"),
-    ("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"),
-    ("cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::cmp::Ord"),
+const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
+    ShouldImplTraitCase::new("std::ops::Add", "add",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::convert::AsMut", "as_mut",  1,  &FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::convert::AsRef", "as_ref",  1,  &FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::ops::BitAnd", "bitand",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::BitOr", "bitor",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::BitXor", "bitxor",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::borrow::Borrow", "borrow",  1,  &FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut",  1,  &FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::clone::Clone", "clone",  1,  &FN_HEADER,  SelfKind::Ref,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::cmp::Ord", "cmp",  2,  &FN_HEADER,  SelfKind::Ref,  OutType::Any, true),
     // FIXME: default doesn't work
-    ("default", 0, &FN_HEADER, SelfKind::No, OutType::Any, "std::default::Default"),
-    ("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"),
-    ("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"),
-    ("div", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Div"),
-    ("drop", 1, &FN_HEADER, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"),
-    ("eq", 2, &FN_HEADER, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"),
-    ("from_iter", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::iter::FromIterator"),
-    ("from_str", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::str::FromStr"),
-    ("hash", 2, &FN_HEADER, SelfKind::Ref, OutType::Unit, "std::hash::Hash"),
-    ("index", 2, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Index"),
-    ("index_mut", 2, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"),
-    ("into_iter", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"),
-    ("mul", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Mul"),
-    ("neg", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Neg"),
-    ("next", 1, &FN_HEADER, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"),
-    ("not", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Not"),
-    ("rem", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Rem"),
-    ("shl", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shl"),
-    ("shr", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shr"),
-    ("sub", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Sub"),
+    ShouldImplTraitCase::new("std::default::Default", "default",  0,  &FN_HEADER,  SelfKind::No,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Deref", "deref",  1,  &FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut",  1,  &FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::ops::Div", "div",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Drop", "drop",  1,  &FN_HEADER,  SelfKind::RefMut,  OutType::Unit, true),
+    ShouldImplTraitCase::new("std::cmp::PartialEq", "eq",  2,  &FN_HEADER,  SelfKind::Ref,  OutType::Bool, true),
+    ShouldImplTraitCase::new("std::iter::FromIterator", "from_iter",  1,  &FN_HEADER,  SelfKind::No,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::str::FromStr", "from_str",  1,  &FN_HEADER,  SelfKind::No,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::hash::Hash", "hash",  2,  &FN_HEADER,  SelfKind::Ref,  OutType::Unit, true),
+    ShouldImplTraitCase::new("std::ops::Index", "index",  2,  &FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::ops::IndexMut", "index_mut",  2,  &FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
+    ShouldImplTraitCase::new("std::iter::IntoIterator", "into_iter",  1,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Mul", "mul",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Neg", "neg",  1,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::iter::Iterator", "next",  1,  &FN_HEADER,  SelfKind::RefMut,  OutType::Any, false),
+    ShouldImplTraitCase::new("std::ops::Not", "not",  1,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Rem", "rem",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Shl", "shl",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Shr", "shr",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
+    ShouldImplTraitCase::new("std::ops::Sub", "sub",  2,  &FN_HEADER,  SelfKind::Value,  OutType::Any, true),
 ];
 
 #[rustfmt::skip]
index adf81607440d1013507c63cca43b1bdfd0c176e2..80dd2f744b3a1137c06f513a4329afee18f9de9f 100644 (file)
 
 use option_helpers::IteratorFalsePositives;
 
-pub struct T;
-
-impl T {
-    // *******************************************
-    // complete trait method list, should lint all
-    // *******************************************
-    pub fn add(self, other: T) -> T {
-        unimplemented!()
-    }
-
-    pub fn as_mut(&mut self) -> &mut T {
-        unimplemented!()
-    }
-
-    pub fn as_ref(&self) -> &T {
-        unimplemented!()
-    }
-
-    pub fn bitand(self, rhs: T) -> T {
-        unimplemented!()
-    }
-
-    pub fn bitor(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn bitxor(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn borrow(&self) -> &str {
-        unimplemented!()
-    }
-
-    pub fn borrow_mut(&mut self) -> &mut str {
-        unimplemented!()
-    }
-
-    pub fn clone(&self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn cmp(&self, other: &Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn default() -> Self {
-        unimplemented!()
-    }
-
-    pub fn deref(&self) -> &Self {
-        unimplemented!()
-    }
-
-    pub fn deref_mut(&mut self) -> &mut Self {
-        unimplemented!()
-    }
-
-    pub fn div(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn drop(&mut self) {
-        unimplemented!()
-    }
-
-    pub fn eq(&self, other: &Self) -> bool {
-        unimplemented!()
-    }
-
-    pub fn from_iter<T>(iter: T) -> Self {
-        unimplemented!()
-    }
-
-    pub fn from_str(s: &str) -> Result<Self, Self> {
-        unimplemented!()
-    }
-
-    pub fn hash(&self, state: &mut T) {
-        unimplemented!()
-    }
-
-    pub fn index(&self, index: usize) -> &Self {
-        unimplemented!()
-    }
-
-    pub fn index_mut(&mut self, index: usize) -> &mut Self {
-        unimplemented!()
-    }
-
-    pub fn into_iter(self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn mul(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn neg(self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn next(&mut self) -> Option<Self> {
-        unimplemented!()
-    }
-
-    pub fn not(self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn rem(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn shl(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn shr(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-
-    pub fn sub(self, rhs: Self) -> Self {
-        unimplemented!()
-    }
-    // *****************
-    // complete list end
-    // *****************
-}
-
-pub struct T1;
-impl T1 {
-    // corner cases: should not lint
-
-    // no error, not public interface
-    pub(crate) fn drop(&mut self) {}
-
-    // no error, private function
-    fn neg(self) -> Self {
-        self
-    }
-
-    // no error, private function
-    fn eq(&self, other: Self) -> bool {
-        true
-    }
-
-    // No error; self is a ref.
-    fn sub(&self, other: Self) -> &Self {
-        self
-    }
-
-    // No error; different number of arguments.
-    fn div(self) -> Self {
-        self
-    }
-
-    // No error; wrong return type.
-    fn rem(self, other: Self) {}
-
-    // Fine
-    fn into_u32(self) -> u32 {
-        0
-    }
-
-    fn into_u16(&self) -> u16 {
-        0
-    }
-
-    fn to_something(self) -> u32 {
-        0
-    }
-
-    fn new(self) -> Self {
-        unimplemented!();
-    }
-
-    pub fn next<'b>(&'b mut self) -> Option<&'b mut T> {
-        unimplemented!();
-    }
-}
-
-pub struct T2;
-impl T2 {
-    // Shouldn't trigger lint as it is unsafe.
-    pub unsafe fn add(self, rhs: Self) -> Self {
-        self
-    }
-
-    // Should not trigger lint since this is an async function.
-    pub async fn next(&mut self) -> Option<Self> {
-        None
-    }
-}
-
 struct Lt<'a> {
     foo: &'a u32,
 }
@@ -302,6 +107,8 @@ fn new() -> i32 {
     }
 }
 
+struct T;
+
 impl Mul<T> for T {
     type Output = T;
     // No error, obviously.
index 5105fff8f5b8a0a55663e5d1ea91a4f24a6bb7c4..2a0a43e83a653089158ed99ac5e80d4d729ad8f7 100644 (file)
@@ -1,249 +1,5 @@
-error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:43:5
-   |
-LL | /     pub fn add(self, other: T) -> T {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-   |
-   = note: `-D clippy::should-implement-trait` implied by `-D warnings`
-
-error: defining a method called `as_mut` on this type; consider implementing the `std::convert::AsMut` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:47:5
-   |
-LL | /     pub fn as_mut(&mut self) -> &mut T {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `as_ref` on this type; consider implementing the `std::convert::AsRef` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:51:5
-   |
-LL | /     pub fn as_ref(&self) -> &T {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `bitand` on this type; consider implementing the `std::ops::BitAnd` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:55:5
-   |
-LL | /     pub fn bitand(self, rhs: T) -> T {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `bitor` on this type; consider implementing the `std::ops::BitOr` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:59:5
-   |
-LL | /     pub fn bitor(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `bitxor` on this type; consider implementing the `std::ops::BitXor` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:63:5
-   |
-LL | /     pub fn bitxor(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `borrow` on this type; consider implementing the `std::borrow::Borrow` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:67:5
-   |
-LL | /     pub fn borrow(&self) -> &str {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `borrow_mut` on this type; consider implementing the `std::borrow::BorrowMut` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:71:5
-   |
-LL | /     pub fn borrow_mut(&mut self) -> &mut str {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `clone` on this type; consider implementing the `std::clone::Clone` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:75:5
-   |
-LL | /     pub fn clone(&self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `cmp` on this type; consider implementing the `std::cmp::Ord` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:79:5
-   |
-LL | /     pub fn cmp(&self, other: &Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `deref` on this type; consider implementing the `std::ops::Deref` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:87:5
-   |
-LL | /     pub fn deref(&self) -> &Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `deref_mut` on this type; consider implementing the `std::ops::DerefMut` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:91:5
-   |
-LL | /     pub fn deref_mut(&mut self) -> &mut Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `div` on this type; consider implementing the `std::ops::Div` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:95:5
-   |
-LL | /     pub fn div(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `drop` on this type; consider implementing the `std::ops::Drop` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:99:5
-   |
-LL | /     pub fn drop(&mut self) {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `eq` on this type; consider implementing the `std::cmp::PartialEq` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:103:5
-   |
-LL | /     pub fn eq(&self, other: &Self) -> bool {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `from_iter` on this type; consider implementing the `std::iter::FromIterator` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:107:5
-   |
-LL | /     pub fn from_iter<T>(iter: T) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `from_str` on this type; consider implementing the `std::str::FromStr` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:111:5
-   |
-LL | /     pub fn from_str(s: &str) -> Result<Self, Self> {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: docs for function returning `Result` missing `# Errors` section
-  --> $DIR/methods.rs:111:5
-   |
-LL | /     pub fn from_str(s: &str) -> Result<Self, Self> {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-   |
-   = note: `-D clippy::missing-errors-doc` implied by `-D warnings`
-
-error: defining a method called `hash` on this type; consider implementing the `std::hash::Hash` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:115:5
-   |
-LL | /     pub fn hash(&self, state: &mut T) {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `index` on this type; consider implementing the `std::ops::Index` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:119:5
-   |
-LL | /     pub fn index(&self, index: usize) -> &Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `index_mut` on this type; consider implementing the `std::ops::IndexMut` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:123:5
-   |
-LL | /     pub fn index_mut(&mut self, index: usize) -> &mut Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `into_iter` on this type; consider implementing the `std::iter::IntoIterator` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:127:5
-   |
-LL | /     pub fn into_iter(self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `mul` on this type; consider implementing the `std::ops::Mul` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:131:5
-   |
-LL | /     pub fn mul(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `neg` on this type; consider implementing the `std::ops::Neg` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:135:5
-   |
-LL | /     pub fn neg(self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `next` on this type; consider implementing the `std::iter::Iterator` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:139:5
-   |
-LL | /     pub fn next(&mut self) -> Option<Self> {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `not` on this type; consider implementing the `std::ops::Not` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:143:5
-   |
-LL | /     pub fn not(self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `rem` on this type; consider implementing the `std::ops::Rem` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:147:5
-   |
-LL | /     pub fn rem(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `shl` on this type; consider implementing the `std::ops::Shl` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:151:5
-   |
-LL | /     pub fn shl(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `shr` on this type; consider implementing the `std::ops::Shr` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:155:5
-   |
-LL | /     pub fn shr(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
-error: defining a method called `sub` on this type; consider implementing the `std::ops::Sub` trait or choosing a less ambiguous name
-  --> $DIR/methods.rs:159:5
-   |
-LL | /     pub fn sub(self, rhs: Self) -> Self {
-LL | |         unimplemented!()
-LL | |     }
-   | |_____^
-
 error: methods called `new` usually return `Self`
-  --> $DIR/methods.rs:300:5
+  --> $DIR/methods.rs:105:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -253,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
-  --> $DIR/methods.rs:319:13
+  --> $DIR/methods.rs:126:13
    |
 LL |     let _ = v.iter().filter(|&x| *x < 0).next();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -262,7 +18,7 @@ LL |     let _ = v.iter().filter(|&x| *x < 0).next();
    = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)`
 
 error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
-  --> $DIR/methods.rs:322:13
+  --> $DIR/methods.rs:129:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
@@ -272,7 +28,7 @@ LL | |                    ).next();
    | |___________________________^
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:339:22
+  --> $DIR/methods.rs:146:22
    |
 LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)`
@@ -280,25 +36,25 @@ LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
    = note: `-D clippy::search-is-some` implied by `-D warnings`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:340:20
+  --> $DIR/methods.rs:147:20
    |
 LL |     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:341:20
+  --> $DIR/methods.rs:148:20
    |
 LL |     let _ = (0..1).find(|x| *x == 0).is_some();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:342:22
+  --> $DIR/methods.rs:149:22
    |
 LL |     let _ = v.iter().find(|x| **x == 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:345:13
+  --> $DIR/methods.rs:152:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -308,13 +64,13 @@ LL | |                    ).is_some();
    | |______________________________^
 
 error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:351:22
+  --> $DIR/methods.rs:158:22
    |
 LL |     let _ = v.iter().position(|&x| x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
 
 error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:354:13
+  --> $DIR/methods.rs:161:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -324,13 +80,13 @@ LL | |                    ).is_some();
    | |______________________________^
 
 error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:360:22
+  --> $DIR/methods.rs:167:22
    |
 LL |     let _ = v.iter().rposition(|&x| x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
 
 error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:363:13
+  --> $DIR/methods.rs:170:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -339,5 +95,5 @@ LL | |                                }
 LL | |                    ).is_some();
    | |______________________________^
 
-error: aborting due to 42 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/should_impl_trait/corner_cases.rs b/tests/ui/should_impl_trait/corner_cases.rs
new file mode 100644 (file)
index 0000000..6c5ffe6
--- /dev/null
@@ -0,0 +1,83 @@
+// edition:2018
+
+#![warn(clippy::all, clippy::pedantic)]
+#![allow(
+    clippy::missing_errors_doc,
+    clippy::needless_pass_by_value,
+    clippy::must_use_candidate,
+    clippy::unused_self,
+    clippy::needless_lifetimes,
+    clippy::missing_safety_doc,
+    clippy::wrong_self_convention
+)]
+
+use std::ops::Mul;
+use std::rc::{self, Rc};
+use std::sync::{self, Arc};
+
+fn main() {}
+
+pub struct T1;
+impl T1 {
+    // corner cases: should not lint
+
+    // no error, not public interface
+    pub(crate) fn drop(&mut self) {}
+
+    // no error, private function
+    fn neg(self) -> Self {
+        self
+    }
+
+    // no error, private function
+    fn eq(&self, other: Self) -> bool {
+        true
+    }
+
+    // No error; self is a ref.
+    fn sub(&self, other: Self) -> &Self {
+        self
+    }
+
+    // No error; different number of arguments.
+    fn div(self) -> Self {
+        self
+    }
+
+    // No error; wrong return type.
+    fn rem(self, other: Self) {}
+
+    // Fine
+    fn into_u32(self) -> u32 {
+        0
+    }
+
+    fn into_u16(&self) -> u16 {
+        0
+    }
+
+    fn to_something(self) -> u32 {
+        0
+    }
+
+    fn new(self) -> Self {
+        unimplemented!();
+    }
+
+    pub fn next<'b>(&'b mut self) -> Option<&'b mut T1> {
+        unimplemented!();
+    }
+}
+
+pub struct T2;
+impl T2 {
+    // Shouldn't trigger lint as it is unsafe.
+    pub unsafe fn add(self, rhs: Self) -> Self {
+        self
+    }
+
+    // Should not trigger lint since this is an async function.
+    pub async fn next(&mut self) -> Option<Self> {
+        None
+    }
+}
diff --git a/tests/ui/should_impl_trait/method_list_1.rs b/tests/ui/should_impl_trait/method_list_1.rs
new file mode 100644 (file)
index 0000000..f8d248f
--- /dev/null
@@ -0,0 +1,87 @@
+// edition:2018
+
+#![warn(clippy::all, clippy::pedantic)]
+#![allow(
+    clippy::missing_errors_doc,
+    clippy::needless_pass_by_value,
+    clippy::must_use_candidate,
+    clippy::unused_self,
+    clippy::needless_lifetimes,
+    clippy::missing_safety_doc,
+    clippy::wrong_self_convention
+)]
+
+use std::ops::Mul;
+use std::rc::{self, Rc};
+use std::sync::{self, Arc};
+
+fn main() {}
+pub struct T;
+
+impl T {
+    // *****************************************
+    // trait method list part 1, should lint all
+    // *****************************************
+    pub fn add(self, other: T) -> T {
+        unimplemented!()
+    }
+
+    pub fn as_mut(&mut self) -> &mut T {
+        unimplemented!()
+    }
+
+    pub fn as_ref(&self) -> &T {
+        unimplemented!()
+    }
+
+    pub fn bitand(self, rhs: T) -> T {
+        unimplemented!()
+    }
+
+    pub fn bitor(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn bitxor(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn borrow(&self) -> &str {
+        unimplemented!()
+    }
+
+    pub fn borrow_mut(&mut self) -> &mut str {
+        unimplemented!()
+    }
+
+    pub fn clone(&self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn cmp(&self, other: &Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn default() -> Self {
+        unimplemented!()
+    }
+
+    pub fn deref(&self) -> &Self {
+        unimplemented!()
+    }
+
+    pub fn deref_mut(&mut self) -> &mut Self {
+        unimplemented!()
+    }
+
+    pub fn div(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn drop(&mut self) {
+        unimplemented!()
+    }
+    // **********
+    // part 1 end
+    // **********
+}
diff --git a/tests/ui/should_impl_trait/method_list_1.stderr b/tests/ui/should_impl_trait/method_list_1.stderr
new file mode 100644 (file)
index 0000000..2b7d462
--- /dev/null
@@ -0,0 +1,143 @@
+error: method `add` can be confused for the standard trait method `std::ops::Add::add`
+  --> $DIR/method_list_1.rs:25:5
+   |
+LL | /     pub fn add(self, other: T) -> T {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::should-implement-trait` implied by `-D warnings`
+   = help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name
+
+error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
+  --> $DIR/method_list_1.rs:29:5
+   |
+LL | /     pub fn as_mut(&mut self) -> &mut T {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
+
+error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
+  --> $DIR/method_list_1.rs:33:5
+   |
+LL | /     pub fn as_ref(&self) -> &T {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
+
+error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
+  --> $DIR/method_list_1.rs:37:5
+   |
+LL | /     pub fn bitand(self, rhs: T) -> T {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
+
+error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
+  --> $DIR/method_list_1.rs:41:5
+   |
+LL | /     pub fn bitor(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
+
+error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
+  --> $DIR/method_list_1.rs:45:5
+   |
+LL | /     pub fn bitxor(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
+
+error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
+  --> $DIR/method_list_1.rs:49:5
+   |
+LL | /     pub fn borrow(&self) -> &str {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
+
+error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
+  --> $DIR/method_list_1.rs:53:5
+   |
+LL | /     pub fn borrow_mut(&mut self) -> &mut str {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
+
+error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
+  --> $DIR/method_list_1.rs:57:5
+   |
+LL | /     pub fn clone(&self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
+
+error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
+  --> $DIR/method_list_1.rs:61:5
+   |
+LL | /     pub fn cmp(&self, other: &Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
+
+error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
+  --> $DIR/method_list_1.rs:69:5
+   |
+LL | /     pub fn deref(&self) -> &Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
+
+error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
+  --> $DIR/method_list_1.rs:73:5
+   |
+LL | /     pub fn deref_mut(&mut self) -> &mut Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
+
+error: method `div` can be confused for the standard trait method `std::ops::Div::div`
+  --> $DIR/method_list_1.rs:77:5
+   |
+LL | /     pub fn div(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
+
+error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
+  --> $DIR/method_list_1.rs:81:5
+   |
+LL | /     pub fn drop(&mut self) {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Drop` or choosing a less ambiguous method name
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/should_impl_trait/method_list_2.rs b/tests/ui/should_impl_trait/method_list_2.rs
new file mode 100644 (file)
index 0000000..ed5e0d3
--- /dev/null
@@ -0,0 +1,88 @@
+// edition:2018
+
+#![warn(clippy::all, clippy::pedantic)]
+#![allow(
+    clippy::missing_errors_doc,
+    clippy::needless_pass_by_value,
+    clippy::must_use_candidate,
+    clippy::unused_self,
+    clippy::needless_lifetimes,
+    clippy::missing_safety_doc,
+    clippy::wrong_self_convention
+)]
+
+use std::ops::Mul;
+use std::rc::{self, Rc};
+use std::sync::{self, Arc};
+
+fn main() {}
+pub struct T;
+
+impl T {
+    // *****************************************
+    // trait method list part 2, should lint all
+    // *****************************************
+
+    pub fn eq(&self, other: &Self) -> bool {
+        unimplemented!()
+    }
+
+    pub fn from_iter<T>(iter: T) -> Self {
+        unimplemented!()
+    }
+
+    pub fn from_str(s: &str) -> Result<Self, Self> {
+        unimplemented!()
+    }
+
+    pub fn hash(&self, state: &mut T) {
+        unimplemented!()
+    }
+
+    pub fn index(&self, index: usize) -> &Self {
+        unimplemented!()
+    }
+
+    pub fn index_mut(&mut self, index: usize) -> &mut Self {
+        unimplemented!()
+    }
+
+    pub fn into_iter(self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn mul(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn neg(self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn next(&mut self) -> Option<Self> {
+        unimplemented!()
+    }
+
+    pub fn not(self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn rem(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn shl(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn shr(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+
+    pub fn sub(self, rhs: Self) -> Self {
+        unimplemented!()
+    }
+    // **********
+    // part 2 end
+    // **********
+}
diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr
new file mode 100644 (file)
index 0000000..b6fd435
--- /dev/null
@@ -0,0 +1,153 @@
+error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
+  --> $DIR/method_list_2.rs:26:5
+   |
+LL | /     pub fn eq(&self, other: &Self) -> bool {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::should-implement-trait` implied by `-D warnings`
+   = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
+
+error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
+  --> $DIR/method_list_2.rs:30:5
+   |
+LL | /     pub fn from_iter<T>(iter: T) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
+
+error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
+  --> $DIR/method_list_2.rs:34:5
+   |
+LL | /     pub fn from_str(s: &str) -> Result<Self, Self> {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
+
+error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
+  --> $DIR/method_list_2.rs:38:5
+   |
+LL | /     pub fn hash(&self, state: &mut T) {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
+
+error: method `index` can be confused for the standard trait method `std::ops::Index::index`
+  --> $DIR/method_list_2.rs:42:5
+   |
+LL | /     pub fn index(&self, index: usize) -> &Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
+
+error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
+  --> $DIR/method_list_2.rs:46:5
+   |
+LL | /     pub fn index_mut(&mut self, index: usize) -> &mut Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
+
+error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
+  --> $DIR/method_list_2.rs:50:5
+   |
+LL | /     pub fn into_iter(self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
+
+error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
+  --> $DIR/method_list_2.rs:54:5
+   |
+LL | /     pub fn mul(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
+
+error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
+  --> $DIR/method_list_2.rs:58:5
+   |
+LL | /     pub fn neg(self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
+
+error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
+  --> $DIR/method_list_2.rs:62:5
+   |
+LL | /     pub fn next(&mut self) -> Option<Self> {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
+
+error: method `not` can be confused for the standard trait method `std::ops::Not::not`
+  --> $DIR/method_list_2.rs:66:5
+   |
+LL | /     pub fn not(self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
+
+error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
+  --> $DIR/method_list_2.rs:70:5
+   |
+LL | /     pub fn rem(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
+
+error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
+  --> $DIR/method_list_2.rs:74:5
+   |
+LL | /     pub fn shl(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
+
+error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
+  --> $DIR/method_list_2.rs:78:5
+   |
+LL | /     pub fn shr(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
+
+error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
+  --> $DIR/method_list_2.rs:82:5
+   |
+LL | /     pub fn sub(self, rhs: Self) -> Self {
+LL | |         unimplemented!()
+LL | |     }
+   | |_____^
+   |
+   = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name
+
+error: aborting due to 15 previous errors
+