| #![warn(clippy::clone_on_copy)] |
| #![allow( |
| clippy::deref_addrof, |
| clippy::needless_borrow, |
| clippy::no_effect, |
| clippy::unnecessary_operation |
| )] |
| #![expect(clippy::toplevel_ref_arg)] |
| |
| use std::cell::RefCell; |
| |
| fn main() { |
| 42; |
| //~^ clone_on_copy |
| |
| vec![1].clone(); // ok, not a Copy type |
| Some(vec![1]).clone(); // ok, not a Copy type |
| *(&42); |
| //~^ clone_on_copy |
| |
| let rc = RefCell::new(0); |
| *rc.borrow(); |
| //~^ clone_on_copy |
| |
| let x = 0u32; |
| x.rotate_left(1); |
| //~^ clone_on_copy |
| |
| #[derive(Clone, Copy)] |
| struct Foo; |
| impl Foo { |
| fn clone(&self) -> u32 { |
| 0 |
| } |
| } |
| Foo.clone(); // ok, this is not the clone trait |
| |
| macro_rules! m { |
| ($e:expr) => {{ $e }}; |
| } |
| m!(42); |
| //~^ clone_on_copy |
| |
| struct Wrap([u32; 2]); |
| impl core::ops::Deref for Wrap { |
| type Target = [u32; 2]; |
| fn deref(&self) -> &[u32; 2] { |
| &self.0 |
| } |
| } |
| let x = Wrap([0, 0]); |
| (*x)[0]; |
| //~^ clone_on_copy |
| |
| let x = 42; |
| let ref y = x.clone(); // ok, binds by reference |
| let ref mut y = x.clone(); // ok, binds by reference |
| } |
| |
| mod issue3052 { |
| struct A; |
| struct B; |
| struct C; |
| struct D; |
| #[derive(Copy, Clone)] |
| struct E; |
| |
| macro_rules! impl_deref { |
| ($src:ident, $dst:ident) => { |
| impl std::ops::Deref for $src { |
| type Target = $dst; |
| fn deref(&self) -> &Self::Target { |
| &$dst |
| } |
| } |
| }; |
| } |
| |
| impl_deref!(A, B); |
| impl_deref!(B, C); |
| impl_deref!(C, D); |
| impl std::ops::Deref for D { |
| type Target = &'static E; |
| fn deref(&self) -> &Self::Target { |
| &&E |
| } |
| } |
| |
| fn go1() { |
| let a = A; |
| let _: E = *****a; |
| //~^ clone_on_copy |
| let _: E = *****a; |
| //~^ clone_on_copy |
| let _: E = *****a; |
| //~^ clone_on_copy |
| let _: E = *****a; |
| //~^ clone_on_copy |
| |
| let _: E = *****a; |
| } |
| } |
| |
| fn issue4348() { |
| fn is_ascii(ch: char) -> bool { |
| ch.is_ascii() |
| } |
| |
| 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate |
| is_ascii('z'); |
| //~^ clone_on_copy |
| } |
| |
| fn issue16969() { |
| let mut x = 43; |
| let _ = &x.clone(); |
| |
| let _ = &mut x.clone(); |
| |
| let mut y = &42; |
| let _ = &y.clone(); |
| |
| let _ = &mut y.clone(); |
| } |
| |
| #[expect(clippy::vec_init_then_push)] |
| fn issue5436() { |
| let mut vec = Vec::new(); |
| vec.push(42); |
| //~^ clone_on_copy |
| } |
| |
| fn issue9277() -> Option<i32> { |
| let opt: &Option<i32> = &None; |
| // operator precedence needed (*opt)? |
| let value = (*opt)?; |
| //~^ clone_on_copy |
| None |
| } |
| |
| mod ufcs_clone_on_copy { |
| use std::cell::RefCell; |
| |
| fn is_ascii(ch: char) -> bool { |
| ch.is_ascii() |
| } |
| |
| #[derive(Clone, Copy)] |
| struct Foo; |
| impl Foo { |
| fn clone(&self) -> u32 { |
| 0 |
| } |
| } |
| |
| macro_rules! m { |
| ($e:expr) => {{ $e }}; |
| } |
| |
| #[derive(Clone, Copy)] |
| struct Bar { |
| field: i32, |
| } |
| |
| struct Wrap([u32; 2]); |
| impl core::ops::Deref for Wrap { |
| type Target = [u32; 2]; |
| fn deref(&self) -> &[u32; 2] { |
| &self.0 |
| } |
| } |
| |
| fn foo(_x: &i32) {} |
| |
| fn main() { |
| let mut x = 42_i32; |
| |
| let vec = vec![1]; |
| let _ = Vec::clone(&vec); // ok, not a Copy type |
| let _ = Clone::clone(&vec); // ok, not a Copy type |
| let opt_vec = Some(vec![1]); |
| let _ = Option::clone(&opt_vec); // ok, not a Copy type |
| let _ = Clone::clone(&opt_vec); // ok, not a Copy type |
| |
| let _ = x; |
| //~^ clone_on_copy |
| let _ = x; |
| //~^ clone_on_copy |
| let _ = x; |
| //~^ clone_on_copy |
| |
| let ref_ref = &&42_i32; |
| // Clone::clone(ref_ref) and <&i32 as Clone>::clone(ref_ref) both return &i32, so it should be |
| // linted. |
| let _ = *ref_ref; |
| //~^ clone_on_copy |
| let _ = *ref_ref; |
| //~^ clone_on_copy |
| |
| let imm_ref = &mut 43_i32; |
| let _ = *imm_ref; |
| //~^ clone_on_copy |
| let _ = *imm_ref; |
| //~^ clone_on_copy |
| let _ = *imm_ref; |
| //~^ clone_on_copy |
| |
| let x_ref = &mut x; |
| let _ = *x_ref; |
| //~^ clone_on_copy |
| let _ = *x_ref; |
| //~^ clone_on_copy |
| let _ = *x_ref; |
| //~^ clone_on_copy |
| |
| let _ = x.rotate_left(1); |
| //~^ clone_on_copy |
| let _ = x.rotate_left(1); |
| //~^ clone_on_copy |
| let _ = x.rotate_left(1); |
| //~^ clone_on_copy |
| |
| char::clone(&'a').make_ascii_uppercase(); // ok, clone and then mutate |
| Clone::clone(&'a').make_ascii_uppercase(); // ok, clone and then mutate |
| <char as Clone>::clone(&'a').make_ascii_uppercase(); // ok, clone and then mutate |
| |
| is_ascii('z'); |
| //~^ clone_on_copy |
| is_ascii('z'); |
| //~^ clone_on_copy |
| is_ascii('z'); |
| //~^ clone_on_copy |
| |
| let _ = Foo::clone(&Foo); // ok, this is not the clone trait |
| |
| let _ = m!(42); |
| //~^ clone_on_copy |
| |
| let rc = RefCell::new(0); |
| let _ = *rc.borrow(); |
| //~^ clone_on_copy |
| |
| let bar = Bar { field: 0 }; |
| let _ = bar.field; |
| //~^ clone_on_copy |
| |
| let array = [0, 0]; |
| let _ = array[0]; |
| //~^ clone_on_copy |
| |
| let wrapped = Wrap([0, 0]); |
| let _ = (*wrapped)[0]; |
| //~^ clone_on_copy |
| |
| let _: &i32 = &i32::clone(&x); |
| let _: &i32 = &Clone::clone(&x); |
| let _: &i32 = &<i32 as Clone>::clone(&x); |
| |
| let _: &mut i32 = &mut i32::clone(&x); |
| let _: &mut i32 = &mut Clone::clone(&x); |
| let _: &mut i32 = &mut <i32 as Clone>::clone(&x); |
| |
| let ref _y = i32::clone(&x); // ok, binds by reference |
| let ref _y = Clone::clone(&x); // ok, binds by reference |
| let ref mut _y = <i32 as Clone>::clone(&x); // ok, binds by reference |
| |
| foo(&i32::clone(&x)); |
| foo(&Clone::clone(&x)); |
| foo(&<i32 as Clone>::clone(&x)); |
| } |
| |
| fn option_clone_on_copy() -> Option<i32> { |
| let opt: &Option<i32> = &Some(0); |
| |
| let _ = (*opt)?; |
| //~^ clone_on_copy |
| let _ = (*opt)?; |
| //~^ clone_on_copy |
| let _ = (*opt)?; |
| //~^ clone_on_copy |
| None |
| } |
| } |