about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTim Nielens <tim.nielens@gmail.com>2020-06-19 22:12:51 +0200
committerTim Nielens <tim.nielens@gmail.com>2020-08-09 15:10:00 +0200
commit2bc0ecd44b4d09476eade641e02451d949a1c8e2 (patch)
tree2ddf37f8f6b3d509a0b8b4adca59539fc4cd1236
parenta77e881ec9f324cdc544150f897d8b34281f92e4 (diff)
downloadrust-2bc0ecd44b4d09476eade641e02451d949a1c8e2.tar.gz
rust-2bc0ecd44b4d09476eade641e02451d949a1c8e2.zip
should_implement_trait - add test cases for every checked trait method
-rw-r--r--clippy_lints/src/methods/mod.rs1
-rw-r--r--tests/ui/methods.rs146
-rw-r--r--tests/ui/methods.stderr264
3 files changed, 386 insertions, 25 deletions
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 3009aa3a64e..c225a3bd359 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -3424,6 +3424,7 @@ const TRAIT_METHODS: [(&str, usize, &hir::FnHeader, SelfKind, OutType, &str); 30
     ("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"),
+    // 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"),
diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs
index 3b267b0dab2..adf81607440 100644
--- a/tests/ui/methods.rs
+++ b/tests/ui/methods.rs
@@ -37,9 +37,136 @@ use option_helpers::IteratorFalsePositives;
 pub struct T;
 
 impl T {
+    // *******************************************
+    // complete trait method list, should lint all
+    // *******************************************
     pub fn add(self, other: T) -> T {
-        self
+        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) {}
@@ -50,22 +177,22 @@ impl T {
     }
 
     // no error, private function
-    fn eq(&self, other: T) -> bool {
+    fn eq(&self, other: Self) -> bool {
         true
     }
 
     // No error; self is a ref.
-    fn sub(&self, other: T) -> &T {
+    fn sub(&self, other: Self) -> &Self {
         self
     }
 
     // No error; different number of arguments.
-    fn div(self) -> T {
+    fn div(self) -> Self {
         self
     }
 
     // No error; wrong return type.
-    fn rem(self, other: T) {}
+    fn rem(self, other: Self) {}
 
     // Fine
     fn into_u32(self) -> u32 {
@@ -89,16 +216,15 @@ impl T {
     }
 }
 
-pub struct T1;
-
-impl T1 {
+pub struct T2;
+impl T2 {
     // Shouldn't trigger lint as it is unsafe.
-    pub unsafe fn add(self, rhs: T1) -> T1 {
+    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<T1> {
+    pub async fn next(&mut self) -> Option<Self> {
         None
     }
 }
diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr
index 9b8ecaed692..5105fff8f5b 100644
--- a/tests/ui/methods.stderr
+++ b/tests/ui/methods.stderr
@@ -1,15 +1,249 @@
 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:40:5
+  --> $DIR/methods.rs:43:5
    |
 LL | /     pub fn add(self, other: T) -> T {
-LL | |         self
+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:174:5
+  --> $DIR/methods.rs:300:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -19,7 +253,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:193:13
+  --> $DIR/methods.rs:319:13
    |
 LL |     let _ = v.iter().filter(|&x| *x < 0).next();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +262,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:196:13
+  --> $DIR/methods.rs:322:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
@@ -38,7 +272,7 @@ LL | |                    ).next();
    | |___________________________^
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:213:22
+  --> $DIR/methods.rs:339:22
    |
 LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)`
@@ -46,25 +280,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:214:20
+  --> $DIR/methods.rs:340: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:215:20
+  --> $DIR/methods.rs:341: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:216:22
+  --> $DIR/methods.rs:342: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:219:13
+  --> $DIR/methods.rs:345:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -74,13 +308,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:225:22
+  --> $DIR/methods.rs:351: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:228:13
+  --> $DIR/methods.rs:354:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -90,13 +324,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:234:22
+  --> $DIR/methods.rs:360: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:237:13
+  --> $DIR/methods.rs:363:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -105,5 +339,5 @@ LL | |                                }
 LL | |                    ).is_some();
    | |______________________________^
 
-error: aborting due to 13 previous errors
+error: aborting due to 42 previous errors