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
+ )
+ );
}
}
}
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]
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,
}
}
}
+struct T;
+
impl Mul<T> for T {
type Output = T;
// No error, obviously.
-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
= 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();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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| {
| _____________^
| |___________________________^
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)`
= 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| {
| _____________^
| |______________________________^
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| {
| _____________^
| |______________________________^
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| {
| _____________^
LL | | ).is_some();
| |______________________________^
-error: aborting due to 42 previous errors
+error: aborting due to 12 previous errors
--- /dev/null
+// 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
+ }
+}
--- /dev/null
+// 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
+ // **********
+}
--- /dev/null
+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
+
--- /dev/null
+// 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
+ // **********
+}
--- /dev/null
+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
+