Skip to content

Commit 14d36c7

Browse files
authored
split unnecessary_clone test into clone_on_ref_ptr and clone_on_copy (#15738)
changelog: none
2 parents 9bcc8a4 + 220e137 commit 14d36c7

8 files changed

+261
-211
lines changed

tests/ui/clone_on_copy.fixed

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
1+
#![warn(clippy::clone_on_copy)]
12
#![allow(
2-
unused,
33
clippy::redundant_clone,
44
clippy::deref_addrof,
55
clippy::no_effect,
66
clippy::unnecessary_operation,
7-
clippy::vec_init_then_push,
87
clippy::toplevel_ref_arg,
98
clippy::needless_borrow
109
)]
1110

1211
use std::cell::RefCell;
13-
use std::rc::{self, Rc};
14-
use std::sync::{self, Arc};
1512

16-
fn main() {}
17-
18-
fn is_ascii(ch: char) -> bool {
19-
ch.is_ascii()
20-
}
21-
22-
fn clone_on_copy() -> Option<(i32)> {
13+
fn main() {
2314
42;
2415
//~^ clone_on_copy
2516

@@ -65,20 +56,66 @@ fn clone_on_copy() -> Option<(i32)> {
6556
let x = 42;
6657
let ref y = x.clone(); // ok, binds by reference
6758
let ref mut y = x.clone(); // ok, binds by reference
59+
}
60+
61+
mod issue3052 {
62+
struct A;
63+
struct B;
64+
struct C;
65+
struct D;
66+
#[derive(Copy, Clone)]
67+
struct E;
68+
69+
macro_rules! impl_deref {
70+
($src:ident, $dst:ident) => {
71+
impl std::ops::Deref for $src {
72+
type Target = $dst;
73+
fn deref(&self) -> &Self::Target {
74+
&$dst
75+
}
76+
}
77+
};
78+
}
79+
80+
impl_deref!(A, B);
81+
impl_deref!(B, C);
82+
impl_deref!(C, D);
83+
impl std::ops::Deref for D {
84+
type Target = &'static E;
85+
fn deref(&self) -> &Self::Target {
86+
&&E
87+
}
88+
}
89+
90+
fn go1() {
91+
let a = A;
92+
let _: E = *****a;
93+
//~^ clone_on_copy
94+
95+
let _: E = *****a;
96+
}
97+
}
98+
99+
fn issue4348() {
100+
fn is_ascii(ch: char) -> bool {
101+
ch.is_ascii()
102+
}
68103

69-
// Issue #4348
70104
let mut x = 43;
71105
let _ = &x.clone(); // ok, getting a ref
72106
'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate
73107
is_ascii('z');
74108
//~^ clone_on_copy
109+
}
75110

76-
// Issue #5436
111+
#[expect(clippy::vec_init_then_push)]
112+
fn issue5436() {
77113
let mut vec = Vec::new();
78114
vec.push(42);
79115
//~^ clone_on_copy
116+
}
80117

81-
// Issue #9277
118+
fn issue9277() -> Option<i32> {
82119
let opt: &Option<i32> = &None;
83120
let value = (*opt)?; // operator precedence needed (*opt)?
84121
//

tests/ui/clone_on_copy.rs

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
1+
#![warn(clippy::clone_on_copy)]
12
#![allow(
2-
unused,
33
clippy::redundant_clone,
44
clippy::deref_addrof,
55
clippy::no_effect,
66
clippy::unnecessary_operation,
7-
clippy::vec_init_then_push,
87
clippy::toplevel_ref_arg,
98
clippy::needless_borrow
109
)]
1110

1211
use std::cell::RefCell;
13-
use std::rc::{self, Rc};
14-
use std::sync::{self, Arc};
1512

16-
fn main() {}
17-
18-
fn is_ascii(ch: char) -> bool {
19-
ch.is_ascii()
20-
}
21-
22-
fn clone_on_copy() -> Option<(i32)> {
13+
fn main() {
2314
42.clone();
2415
//~^ clone_on_copy
2516

@@ -65,20 +56,66 @@ fn clone_on_copy() -> Option<(i32)> {
6556
let x = 42;
6657
let ref y = x.clone(); // ok, binds by reference
6758
let ref mut y = x.clone(); // ok, binds by reference
59+
}
60+
61+
mod issue3052 {
62+
struct A;
63+
struct B;
64+
struct C;
65+
struct D;
66+
#[derive(Copy, Clone)]
67+
struct E;
68+
69+
macro_rules! impl_deref {
70+
($src:ident, $dst:ident) => {
71+
impl std::ops::Deref for $src {
72+
type Target = $dst;
73+
fn deref(&self) -> &Self::Target {
74+
&$dst
75+
}
76+
}
77+
};
78+
}
79+
80+
impl_deref!(A, B);
81+
impl_deref!(B, C);
82+
impl_deref!(C, D);
83+
impl std::ops::Deref for D {
84+
type Target = &'static E;
85+
fn deref(&self) -> &Self::Target {
86+
&&E
87+
}
88+
}
89+
90+
fn go1() {
91+
let a = A;
92+
let _: E = a.clone();
93+
//~^ clone_on_copy
94+
95+
let _: E = *****a;
96+
}
97+
}
98+
99+
fn issue4348() {
100+
fn is_ascii(ch: char) -> bool {
101+
ch.is_ascii()
102+
}
68103

69-
// Issue #4348
70104
let mut x = 43;
71105
let _ = &x.clone(); // ok, getting a ref
72106
'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate
73107
is_ascii('z'.clone());
74108
//~^ clone_on_copy
109+
}
75110

76-
// Issue #5436
111+
#[expect(clippy::vec_init_then_push)]
112+
fn issue5436() {
77113
let mut vec = Vec::new();
78114
vec.push(42.clone());
79115
//~^ clone_on_copy
116+
}
80117

81-
// Issue #9277
118+
fn issue9277() -> Option<i32> {
82119
let opt: &Option<i32> = &None;
83120
let value = opt.clone()?; // operator precedence needed (*opt)?
84121
//

tests/ui/clone_on_copy.stderr

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: using `clone` on type `i32` which implements the `Copy` trait
2-
--> tests/ui/clone_on_copy.rs:23:5
2+
--> tests/ui/clone_on_copy.rs:14:5
33
|
44
LL | 42.clone();
55
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
@@ -8,52 +8,58 @@ LL | 42.clone();
88
= help: to override `-D warnings` add `#[allow(clippy::clone_on_copy)]`
99

1010
error: using `clone` on type `i32` which implements the `Copy` trait
11-
--> tests/ui/clone_on_copy.rs:28:5
11+
--> tests/ui/clone_on_copy.rs:19:5
1212
|
1313
LL | (&42).clone();
1414
| ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
1515

1616
error: using `clone` on type `i32` which implements the `Copy` trait
17-
--> tests/ui/clone_on_copy.rs:32:5
17+
--> tests/ui/clone_on_copy.rs:23:5
1818
|
1919
LL | rc.borrow().clone();
2020
| ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
2121

2222
error: using `clone` on type `u32` which implements the `Copy` trait
23-
--> tests/ui/clone_on_copy.rs:36:5
23+
--> tests/ui/clone_on_copy.rs:27:5
2424
|
2525
LL | x.clone().rotate_left(1);
2626
| ^^^^^^^^^ help: try removing the `clone` call: `x`
2727

2828
error: using `clone` on type `i32` which implements the `Copy` trait
29-
--> tests/ui/clone_on_copy.rs:51:5
29+
--> tests/ui/clone_on_copy.rs:42:5
3030
|
3131
LL | m!(42).clone();
3232
| ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)`
3333

3434
error: using `clone` on type `[u32; 2]` which implements the `Copy` trait
35-
--> tests/ui/clone_on_copy.rs:62:5
35+
--> tests/ui/clone_on_copy.rs:53:5
3636
|
3737
LL | x.clone()[0];
3838
| ^^^^^^^^^ help: try dereferencing it: `(*x)`
3939

40+
error: using `clone` on type `E` which implements the `Copy` trait
41+
--> tests/ui/clone_on_copy.rs:92:20
42+
|
43+
LL | let _: E = a.clone();
44+
| ^^^^^^^^^ help: try dereferencing it: `*****a`
45+
4046
error: using `clone` on type `char` which implements the `Copy` trait
41-
--> tests/ui/clone_on_copy.rs:73:14
47+
--> tests/ui/clone_on_copy.rs:107:14
4248
|
4349
LL | is_ascii('z'.clone());
4450
| ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
4551

4652
error: using `clone` on type `i32` which implements the `Copy` trait
47-
--> tests/ui/clone_on_copy.rs:78:14
53+
--> tests/ui/clone_on_copy.rs:114:14
4854
|
4955
LL | vec.push(42.clone());
5056
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
5157

5258
error: using `clone` on type `Option<i32>` which implements the `Copy` trait
53-
--> tests/ui/clone_on_copy.rs:83:17
59+
--> tests/ui/clone_on_copy.rs:120:17
5460
|
5561
LL | let value = opt.clone()?; // operator precedence needed (*opt)?
5662
| ^^^^^^^^^^^ help: try dereferencing it: `(*opt)`
5763

58-
error: aborting due to 9 previous errors
64+
error: aborting due to 10 previous errors
5965

tests/ui/clone_on_ref_ptr.fixed

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![warn(clippy::clone_on_ref_ptr)]
2+
3+
use std::rc::{Rc, Weak as RcWeak};
4+
use std::sync::{Arc, Weak as ArcWeak};
5+
6+
fn main() {}
7+
8+
fn clone_on_ref_ptr(rc: Rc<str>, rc_weak: RcWeak<str>, arc: Arc<str>, arc_weak: ArcWeak<str>) {
9+
std::rc::Rc::<str>::clone(&rc);
10+
//~^ clone_on_ref_ptr
11+
std::rc::Weak::<str>::clone(&rc_weak);
12+
//~^ clone_on_ref_ptr
13+
std::sync::Arc::<str>::clone(&arc);
14+
//~^ clone_on_ref_ptr
15+
std::sync::Weak::<str>::clone(&arc_weak);
16+
//~^ clone_on_ref_ptr
17+
18+
Rc::clone(&rc);
19+
Arc::clone(&arc);
20+
RcWeak::clone(&rc_weak);
21+
ArcWeak::clone(&arc_weak);
22+
}
23+
24+
trait SomeTrait {}
25+
struct SomeImpl;
26+
impl SomeTrait for SomeImpl {}
27+
28+
fn trait_object() {
29+
let x = Arc::new(SomeImpl);
30+
let _: Arc<dyn SomeTrait> = std::sync::Arc::<SomeImpl>::clone(&x);
31+
//~^ clone_on_ref_ptr
32+
}
33+
34+
mod issue2076 {
35+
use std::rc::Rc;
36+
37+
macro_rules! try_opt {
38+
($expr: expr) => {
39+
match $expr {
40+
Some(value) => value,
41+
None => return None,
42+
}
43+
};
44+
}
45+
46+
fn func() -> Option<Rc<u8>> {
47+
let rc = Rc::new(42);
48+
Some(std::rc::Rc::<u8>::clone(&try_opt!(Some(rc))))
49+
//~^ clone_on_ref_ptr
50+
}
51+
}

tests/ui/clone_on_ref_ptr.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![warn(clippy::clone_on_ref_ptr)]
2+
3+
use std::rc::{Rc, Weak as RcWeak};
4+
use std::sync::{Arc, Weak as ArcWeak};
5+
6+
fn main() {}
7+
8+
fn clone_on_ref_ptr(rc: Rc<str>, rc_weak: RcWeak<str>, arc: Arc<str>, arc_weak: ArcWeak<str>) {
9+
rc.clone();
10+
//~^ clone_on_ref_ptr
11+
rc_weak.clone();
12+
//~^ clone_on_ref_ptr
13+
arc.clone();
14+
//~^ clone_on_ref_ptr
15+
arc_weak.clone();
16+
//~^ clone_on_ref_ptr
17+
18+
Rc::clone(&rc);
19+
Arc::clone(&arc);
20+
RcWeak::clone(&rc_weak);
21+
ArcWeak::clone(&arc_weak);
22+
}
23+
24+
trait SomeTrait {}
25+
struct SomeImpl;
26+
impl SomeTrait for SomeImpl {}
27+
28+
fn trait_object() {
29+
let x = Arc::new(SomeImpl);
30+
let _: Arc<dyn SomeTrait> = x.clone();
31+
//~^ clone_on_ref_ptr
32+
}
33+
34+
mod issue2076 {
35+
use std::rc::Rc;
36+
37+
macro_rules! try_opt {
38+
($expr: expr) => {
39+
match $expr {
40+
Some(value) => value,
41+
None => return None,
42+
}
43+
};
44+
}
45+
46+
fn func() -> Option<Rc<u8>> {
47+
let rc = Rc::new(42);
48+
Some(try_opt!(Some(rc)).clone())
49+
//~^ clone_on_ref_ptr
50+
}
51+
}

0 commit comments

Comments
 (0)