about summary refs log tree commit diff
path: root/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
blob: 7d101915517fe1202cd8bf42ca9dcdc196748961 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//@aux-build:proc_macro_derive.rs
#![allow(clippy::clone_on_copy, unused)]
#![allow(clippy::assigning_clones)]
#![no_main]

extern crate proc_macros;
use proc_macros::with_span;

// lint

struct A(u32);

impl Clone for A {
    fn clone(&self) -> Self {
        //~^ non_canonical_clone_impl
        Self(self.0)
    }

    fn clone_from(&mut self, source: &Self) {
        //~^ non_canonical_clone_impl
        source.clone();
        *self = source.clone();
    }
}

impl Copy for A {}

// do not lint

struct B(u32);

impl Clone for B {
    fn clone(&self) -> Self {
        *self
    }
}

impl Copy for B {}

// do not lint derived (clone's implementation is `*self` here anyway)

#[derive(Clone, Copy)]
struct C(u32);

// do not lint derived (fr this time)

struct D(u32);

#[automatically_derived]
impl Clone for D {
    fn clone(&self) -> Self {
        Self(self.0)
    }

    fn clone_from(&mut self, source: &Self) {
        source.clone();
        *self = source.clone();
    }
}

impl Copy for D {}

// do not lint if clone is not manually implemented

struct E(u32);

#[automatically_derived]
impl Clone for E {
    fn clone(&self) -> Self {
        Self(self.0)
    }

    fn clone_from(&mut self, source: &Self) {
        source.clone();
        *self = source.clone();
    }
}

impl Copy for E {}

// lint since clone is not derived

#[derive(Copy)]
struct F(u32);

impl Clone for F {
    fn clone(&self) -> Self {
        //~^ non_canonical_clone_impl
        Self(self.0)
    }

    fn clone_from(&mut self, source: &Self) {
        //~^ non_canonical_clone_impl
        source.clone();
        *self = source.clone();
    }
}

// do not lint since copy has more restrictive bounds

#[derive(Eq, PartialEq)]
struct Uwu<A: Copy>(A);

impl<A: Copy> Clone for Uwu<A> {
    fn clone(&self) -> Self {
        Self(self.0)
    }

    fn clone_from(&mut self, source: &Self) {
        source.clone();
        *self = source.clone();
    }
}

impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}

// should skip proc macros, see https://github.com/rust-lang/rust-clippy/issues/12788
#[derive(proc_macro_derive::NonCanonicalClone)]
pub struct G;

with_span!(
    span

    #[derive(Copy)]
    struct H;
    impl Clone for H {
        fn clone(&self) -> Self {
            todo!()
        }
    }
);