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
|
#![warn(clippy::swap_with_temporary)]
use std::mem::swap;
fn func() -> String {
String::from("func")
}
fn func_returning_refmut(s: &mut String) -> &mut String {
s
}
fn main() {
let mut x = String::from("x");
let mut y = String::from("y");
let mut zz = String::from("zz");
let z = &mut zz;
// No lint
swap(&mut x, &mut y);
swap(&mut func(), &mut y);
//~^ ERROR: swapping with a temporary value is inefficient
swap(&mut x, &mut func());
//~^ ERROR: swapping with a temporary value is inefficient
swap(z, &mut func());
//~^ ERROR: swapping with a temporary value is inefficient
// No lint
swap(z, func_returning_refmut(&mut x));
swap(&mut y, z);
swap(&mut func(), z);
//~^ ERROR: swapping with a temporary value is inefficient
macro_rules! mac {
(refmut $x:expr) => {
&mut $x
};
(funcall $f:ident) => {
$f()
};
(wholeexpr) => {
swap(&mut 42, &mut 0)
};
(ident $v:ident) => {
$v
};
}
swap(&mut mac!(funcall func), z);
//~^ ERROR: swapping with a temporary value is inefficient
swap(&mut mac!(funcall func), mac!(ident z));
//~^ ERROR: swapping with a temporary value is inefficient
swap(mac!(ident z), &mut mac!(funcall func));
//~^ ERROR: swapping with a temporary value is inefficient
swap(mac!(refmut y), &mut func());
//~^ ERROR: swapping with a temporary value is inefficient
// No lint if it comes from a macro as it may depend on the arguments
mac!(wholeexpr);
}
struct S {
t: String,
}
fn dont_lint_those(s: &mut S, v: &mut [String], w: Option<&mut String>) {
swap(&mut s.t, &mut v[0]);
swap(&mut s.t, v.get_mut(0).unwrap());
swap(w.unwrap(), &mut s.t);
}
fn issue15166() {
use std::sync::Mutex;
struct A {
thing: Mutex<Vec<u8>>,
}
impl A {
fn a(&self) {
let mut new_vec = vec![42];
// Do not lint here, as neither `new_vec` nor the result of `.lock().unwrap()` are temporaries
swap(&mut new_vec, &mut self.thing.lock().unwrap());
for v in new_vec {
// Do something with v
}
// Here `vec![42]` is temporary though, and a proper dereference will have to be used in the fix
swap(&mut vec![42], &mut self.thing.lock().unwrap());
//~^ ERROR: swapping with a temporary value is inefficient
}
}
}
fn multiple_deref() {
let mut v1 = &mut &mut &mut vec![42];
swap(&mut ***v1, &mut vec![]);
//~^ ERROR: swapping with a temporary value is inefficient
struct Wrapper<T: ?Sized>(T);
impl<T: ?Sized> std::ops::Deref for Wrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: ?Sized> std::ops::DerefMut for Wrapper<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
use std::sync::Mutex;
let mut v1 = Mutex::new(Wrapper(Wrapper(vec![42])));
swap(&mut vec![], &mut v1.lock().unwrap());
//~^ ERROR: swapping with a temporary value is inefficient
}
|