//@run-rustfix //@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] #![allow( clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into, clippy::self_named_constructors )] #[macro_use] extern crate proc_macro_derive; fn main() {} mod use_self { struct Foo; impl Foo { fn new() -> Self { Self {} } fn test() -> Self { Self::new() } } impl Default for Foo { fn default() -> Self { Self::new() } } } mod better { struct Foo; impl Foo { fn new() -> Self { Self {} } fn test() -> Self { Self::new() } } impl Default for Foo { fn default() -> Self { Self::new() } } } mod lifetimes { struct Foo<'a> { foo_str: &'a str, } impl<'a> Foo<'a> { // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> // Foo<'b>` fn foo(s: &str) -> Foo { Foo { foo_str: s } } // cannot replace with `Self`, because that's `Foo<'a>` fn bar() -> Foo<'static> { Foo { foo_str: "foo" } } // FIXME: the lint does not handle lifetimed struct // `Self` should be applicable here fn clone(&self) -> Foo<'a> { Foo { foo_str: self.foo_str } } } } mod issue2894 { trait IntoBytes { fn to_bytes(self) -> Vec<u8>; } // This should not be linted impl IntoBytes for u8 { fn to_bytes(self) -> Vec<u8> { vec![self] } } } mod existential { struct Foo; impl Foo { fn bad(foos: &[Self]) -> impl Iterator<Item = &Self> { foos.iter() } fn good(foos: &[Self]) -> impl Iterator<Item = &Self> { foos.iter() } } } mod tuple_structs { pub struct TS(i32); impl TS { pub fn ts() -> Self { Self(0) } } } mod macros { macro_rules! use_self_expand { () => { fn new() -> Foo { Foo {} } }; } struct Foo; impl Foo { use_self_expand!(); // Should not lint in local macros } #[derive(StructAUseSelf)] // Should not lint in derives struct A; } mod nesting { struct Foo; impl Foo { fn foo() { #[allow(unused_imports)] use self::Foo; // Can't use Self here struct Bar { foo: Foo, // Foo != Self } impl Bar { fn bar() -> Self { Self { foo: Foo {} } } } // Can't use Self here fn baz() -> Foo { Foo {} } } // Should lint here fn baz() -> Self { Self {} } } enum Enum { A, B(u64), C { field: bool }, } impl Enum { fn method() { #[allow(unused_imports)] use self::Enum::*; // Issue 3425 static STATIC: Enum = Enum::A; // Can't use Self as type } fn method2() { let _ = Self::B(42); let _ = Self::C { field: true }; let _ = Self::A; } } } mod issue3410 { struct A; struct B; trait Trait<T> { fn a(v: T) -> Self; } impl Trait<Vec<A>> for Vec<B> { fn a(_: Vec<A>) -> Self { unimplemented!() } } impl<T> Trait<Vec<A>> for Vec<T> where T: Trait<B>, { fn a(v: Vec<A>) -> Self { <Vec<B>>::a(v).into_iter().map(Trait::a).collect() } } } #[allow(clippy::no_effect, path_statements)] mod rustfix { mod nested { pub struct A; } impl nested::A { const A: bool = true; fn fun_1() {} fn fun_2() { Self::fun_1(); Self::A; Self {}; } } } mod issue3567 { struct TestStruct; impl TestStruct { fn from_something() -> Self { Self {} } } trait Test { fn test() -> TestStruct; } impl Test for TestStruct { fn test() -> TestStruct { Self::from_something() } } } mod paths_created_by_lowering { use std::ops::Range; struct S; impl S { const A: usize = 0; const B: usize = 1; async fn g() -> Self { Self {} } fn f<'a>(&self, p: &'a [u8]) -> &'a [u8] { &p[Self::A..Self::B] } } trait T { fn f<'a>(&self, p: &'a [u8]) -> &'a [u8]; } impl T for Range<u8> { fn f<'a>(&self, p: &'a [u8]) -> &'a [u8] { &p[0..1] } } } // reused from #1997 mod generics { struct Foo<T> { value: T, } impl<T> Foo<T> { // `Self` is applicable here fn foo(value: T) -> Self { Self { value } } // `Cannot` use `Self` as a return type as the generic types are different fn bar(value: i32) -> Foo<i32> { Foo { value } } } } mod issue4140 { pub struct Error<From, To> { _from: From, _too: To, } pub trait From<T> { type From; type To; fn from(value: T) -> Self; } pub trait TryFrom<T> where Self: Sized, { type From; type To; fn try_from(value: T) -> Result<Self, Error<Self::From, Self::To>>; } // FIXME: Suggested fix results in infinite recursion. // impl<F, T> TryFrom<F> for T // where // T: From<F>, // { // type From = Self::From; // type To = Self::To; // fn try_from(value: F) -> Result<Self, Error<Self::From, Self::To>> { // Ok(From::from(value)) // } // } impl From<bool> for i64 { type From = bool; type To = Self; fn from(value: bool) -> Self { if value { 100 } else { 0 } } } } mod issue2843 { trait Foo { type Bar; } impl Foo for usize { type Bar = u8; } impl<T: Foo> Foo for Option<T> { type Bar = Option<T::Bar>; } } mod issue3859 { pub struct Foo; pub struct Bar([usize; 3]); impl Foo { pub const BAR: usize = 3; pub fn foo() { const _X: usize = Foo::BAR; // const _Y: usize = Self::BAR; } } } mod issue4305 { trait Foo: 'static {} struct Bar; impl Foo for Bar {} impl<T: Foo> From<T> for Box<dyn Foo> { fn from(t: T) -> Self { Box::new(t) } } } mod lint_at_item_level { struct Foo; #[allow(clippy::use_self)] impl Foo { fn new() -> Foo { Foo {} } } #[allow(clippy::use_self)] impl Default for Foo { fn default() -> Foo { Foo::new() } } } mod lint_at_impl_item_level { struct Foo; impl Foo { #[allow(clippy::use_self)] fn new() -> Foo { Foo {} } } impl Default for Foo { #[allow(clippy::use_self)] fn default() -> Foo { Foo::new() } } } mod issue4734 { #[repr(C, packed)] pub struct X { pub x: u32, } impl From<X> for u32 { fn from(c: X) -> Self { unsafe { core::mem::transmute(c) } } } } mod nested_paths { use std::convert::Into; mod submod { pub struct B; pub struct C; impl Into<C> for B { fn into(self) -> C { C {} } } } struct A<T> { t: T, } impl<T> A<T> { fn new<V: Into<T>>(v: V) -> Self { Self { t: Into::into(v) } } } impl A<submod::C> { fn test() -> Self { Self::new::<submod::B>(submod::B {}) } } } mod issue6818 { #[derive(serde::Deserialize)] struct A { a: i32, } } mod issue7206 { struct MyStruct<const C: char>; impl From<MyStruct<'a'>> for MyStruct<'b'> { fn from(_s: MyStruct<'a'>) -> Self { Self } } // keep linting non-`Const` generic args struct S<'a> { inner: &'a str, } struct S2<T> { inner: T, } impl<T> S2<T> { fn new() -> Self { unimplemented!(); } } impl<'a> S2<S<'a>> { fn new_again() -> Self { Self::new() } } } mod self_is_ty_param { trait Trait { type Type; type Hi; fn test(); } impl<I> Trait for I where I: Iterator, I::Item: Trait, // changing this to Self would require <Self as Iterator> { type Type = I; type Hi = I::Item; fn test() { let _: I::Item; let _: I; // this could lint, but is questionable } } } mod use_self_in_pat { enum Foo { Bar, Baz, } impl Foo { fn do_stuff(self) { match self { Self::Bar => unimplemented!(), Self::Baz => unimplemented!(), } match Some(1) { Some(_) => unimplemented!(), None => unimplemented!(), } if let Self::Bar = self { unimplemented!() } } } } mod issue8845 { pub enum Something { Num(u8), TupleNums(u8, u8), StructNums { one: u8, two: u8 }, } struct Foo(u8); struct Bar { x: u8, y: usize, } impl Something { fn get_value(&self) -> u8 { match self { Self::Num(n) => *n, Self::TupleNums(n, _m) => *n, Self::StructNums { one, two: _ } => *one, } } fn use_crate(&self) -> u8 { match self { Self::Num(n) => *n, Self::TupleNums(n, _m) => *n, Self::StructNums { one, two: _ } => *one, } } fn imported_values(&self) -> u8 { use Something::*; match self { Num(n) => *n, TupleNums(n, _m) => *n, StructNums { one, two: _ } => *one, } } } impl Foo { fn get_value(&self) -> u8 { let Self(x) = self; *x } fn use_crate(&self) -> u8 { let Self(x) = self; *x } } impl Bar { fn get_value(&self) -> u8 { let Self { x, .. } = self; *x } fn use_crate(&self) -> u8 { let Self { x, .. } = self; *x } } } mod issue6902 { use serde::Serialize; #[derive(Serialize)] pub enum Foo { Bar = 1, } } #[clippy::msrv = "1.36"] fn msrv_1_36() { enum E { A, } impl E { fn foo(self) { match self { E::A => {}, } } } } #[clippy::msrv = "1.37"] fn msrv_1_37() { enum E { A, } impl E { fn foo(self) { match self { Self::A => {}, } } } } mod issue_10371 { struct Val<const V: i32> {} impl<const V: i32> From<Val<V>> for i32 { fn from(_: Val<V>) -> Self { todo!() } } }