#![warn(clippy::clone_on_copy)]
#![allow(
    clippy::redundant_clone,
    clippy::deref_addrof,
    clippy::no_effect,
    clippy::unnecessary_operation,
    clippy::toplevel_ref_arg,
    clippy::needless_borrow
)]

use std::cell::RefCell;

fn main() {
    42.clone();
    //~^ clone_on_copy

    vec![1].clone(); // ok, not a Copy type
    Some(vec![1]).clone(); // ok, not a Copy type
    (&42).clone();
    //~^ clone_on_copy

    let rc = RefCell::new(0);
    rc.borrow().clone();
    //~^ clone_on_copy

    let x = 0u32;
    x.clone().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();
    //~^ 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.clone()[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();
        //~^ clone_on_copy

        let _: E = *****a;
    }
}

fn issue4348() {
    fn is_ascii(ch: char) -> bool {
        ch.is_ascii()
    }

    let mut x = 43;
    let _ = &x.clone(); // ok, getting a ref
    'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate
    is_ascii('z'.clone());
    //~^ clone_on_copy
}

#[expect(clippy::vec_init_then_push)]
fn issue5436() {
    let mut vec = Vec::new();
    vec.push(42.clone());
    //~^ clone_on_copy
}

fn issue9277() -> Option<i32> {
    let opt: &Option<i32> = &None;
    let value = opt.clone()?; // operator precedence needed (*opt)?
    //
    //~^^ clone_on_copy
    None
}
