should_implement_trait - add test cases for every checked trait method

This commit is contained in:
Tim Nielens 2020-06-19 22:12:51 +02:00
parent a77e881ec9
commit 2bc0ecd44b
3 changed files with 386 additions and 25 deletions

View file

@ -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"), ("borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"),
("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"), ("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"),
("cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), ("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"), ("default", 0, &FN_HEADER, SelfKind::No, OutType::Any, "std::default::Default"),
("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), ("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"),
("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), ("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"),

View file

@ -37,10 +37,137 @@ use option_helpers::IteratorFalsePositives;
pub struct T; pub struct T;
impl T { impl T {
// *******************************************
// complete trait method list, should lint all
// *******************************************
pub fn add(self, other: T) -> T { 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 // no error, not public interface
pub(crate) fn drop(&mut self) {} pub(crate) fn drop(&mut self) {}
@ -50,22 +177,22 @@ impl T {
} }
// no error, private function // no error, private function
fn eq(&self, other: T) -> bool { fn eq(&self, other: Self) -> bool {
true true
} }
// No error; self is a ref. // No error; self is a ref.
fn sub(&self, other: T) -> &T { fn sub(&self, other: Self) -> &Self {
self self
} }
// No error; different number of arguments. // No error; different number of arguments.
fn div(self) -> T { fn div(self) -> Self {
self self
} }
// No error; wrong return type. // No error; wrong return type.
fn rem(self, other: T) {} fn rem(self, other: Self) {}
// Fine // Fine
fn into_u32(self) -> u32 { fn into_u32(self) -> u32 {
@ -89,16 +216,15 @@ impl T {
} }
} }
pub struct T1; pub struct T2;
impl T2 {
impl T1 {
// Shouldn't trigger lint as it is unsafe. // 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 self
} }
// Should not trigger lint since this is an async function. // 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 None
} }
} }

View file

@ -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 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 | / pub fn add(self, other: T) -> T {
LL | | self LL | | unimplemented!()
LL | | } LL | | }
| |_____^ | |_____^
| |
= note: `-D clippy::should-implement-trait` implied by `-D warnings` = 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` error: methods called `new` usually return `Self`
--> $DIR/methods.rs:174:5 --> $DIR/methods.rs:300:5
| |
LL | / fn new() -> i32 { LL | / fn new() -> i32 {
LL | | 0 LL | | 0
@ -19,7 +253,7 @@ LL | | }
= note: `-D clippy::new-ret-no-self` implied by `-D warnings` = 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. 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(); 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)` = 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. 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| { 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()`. 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(); LL | let _ = v.iter().find(|&x| *x < 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` = 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()`. 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 LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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()`. 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(); LL | let _ = (0..1).find(|x| *x == 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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()`. 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(); LL | let _ = v.iter().find(|x| **x == 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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()`. 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| { 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()`. 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(); LL | let _ = v.iter().position(|&x| x < 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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()`. 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| { 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()`. 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(); LL | let _ = v.iter().rposition(|&x| x < 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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()`. 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| { LL | let _ = v.iter().rposition(|&x| {
| _____________^ | _____________^
@ -105,5 +339,5 @@ LL | | }
LL | | ).is_some(); LL | | ).is_some();
| |______________________________^ | |______________________________^
error: aborting due to 13 previous errors error: aborting due to 42 previous errors