Skip to content

Commit 2795a60

Browse files
committed
Auto merge of #12693 - GuillaumeGomez:run-on-self-needless_pass_by_ref_mut, r=Manishearth
Emit the `needless_pass_by_ref_mut` lint on `self` arguments as well Fixes #12589. Fixes #9591. The first commit fixes a bug I uncovered while working on this: sometimes, the mutable borrow "event" happens before the alias one, which makes some argument detected as not used mutably even if they are. The fix was simply to fill the map with the aliases afterwards. The second commit removes the restriction to not run `self` argument for the `needless_pass_by_ref_mut` lint. changelog: emit the `needless_pass_by_ref_mut` lint on `self` arguments as well r? `@Manishearth`
2 parents ca3b393 + 0999867 commit 2795a60

6 files changed

+180
-54
lines changed

clippy_lints/src/needless_pass_by_ref_mut.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ fn should_skip<'tcx>(
8383
}
8484

8585
if is_self(arg) {
86-
return true;
86+
// Interestingly enough, `self` arguments make `is_from_proc_macro` return `true`, hence why
87+
// we return early here.
88+
return false;
8789
}
8890

8991
if let PatKind::Binding(.., name, _) = arg.pat.kind {
@@ -185,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
185187
}
186188
// Collect variables mutably used and spans which will need dereferencings from the
187189
// function body.
188-
let MutablyUsedVariablesCtxt { mutably_used_vars, .. } = {
190+
let mutably_used_vars = {
189191
let mut ctx = MutablyUsedVariablesCtxt {
190192
mutably_used_vars: HirIdSet::default(),
191193
prev_bind: None,
@@ -217,7 +219,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
217219
check_closures(&mut ctx, cx, &infcx, &mut checked_closures, async_closures);
218220
}
219221
}
220-
ctx
222+
ctx.generate_mutably_used_ids_from_aliases()
221223
};
222224
for ((&input, &_), arg) in it {
223225
// Only take `&mut` arguments.
@@ -309,12 +311,22 @@ struct MutablyUsedVariablesCtxt<'tcx> {
309311
}
310312

311313
impl<'tcx> MutablyUsedVariablesCtxt<'tcx> {
312-
fn add_mutably_used_var(&mut self, mut used_id: HirId) {
313-
while let Some(id) = self.aliases.get(&used_id) {
314+
fn add_mutably_used_var(&mut self, used_id: HirId) {
315+
self.mutably_used_vars.insert(used_id);
316+
}
317+
318+
// Because the alias may come after the mutable use of a variable, we need to fill the map at
319+
// the end.
320+
fn generate_mutably_used_ids_from_aliases(mut self) -> HirIdSet {
321+
let all_ids = self.mutably_used_vars.iter().copied().collect::<Vec<_>>();
322+
for mut used_id in all_ids {
323+
while let Some(id) = self.aliases.get(&used_id) {
324+
self.mutably_used_vars.insert(used_id);
325+
used_id = *id;
326+
}
314327
self.mutably_used_vars.insert(used_id);
315-
used_id = *id;
316328
}
317-
self.mutably_used_vars.insert(used_id);
329+
self.mutably_used_vars
318330
}
319331

320332
fn would_be_alias_cycle(&self, alias: HirId, mut target: HirId) -> bool {

tests/ui/needless_pass_by_ref_mut.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,13 @@ fn non_mut_ref(_: &Vec<u32>) {}
4444
struct Bar;
4545

4646
impl Bar {
47-
// Should not warn on `&mut self`.
4847
fn bar(&mut self) {}
48+
//~^ ERROR: this argument is a mutable reference, but not used mutably
4949

5050
fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
5151
//~^ ERROR: this argument is a mutable reference, but not used mutably
5252
vec.len()
5353
}
54-
55-
fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
56-
//~^ ERROR: this argument is a mutable reference, but not used mutably
57-
vec.len()
58-
}
5954
}
6055

6156
trait Babar {
@@ -307,6 +302,41 @@ fn filter_copy<T: Copy>(predicate: &mut impl FnMut(T) -> bool) -> impl FnMut(&T)
307302
move |&item| predicate(item)
308303
}
309304

305+
trait MutSelfTrait {
306+
// Should not warn since it's a trait method.
307+
fn mut_self(&mut self);
308+
}
309+
310+
struct MutSelf {
311+
a: u32,
312+
}
313+
314+
impl MutSelf {
315+
fn bar(&mut self) {}
316+
//~^ ERROR: this argument is a mutable reference, but not used mutably
317+
async fn foo(&mut self, u: &mut i32, v: &mut u32) {
318+
//~^ ERROR: this argument is a mutable reference, but not used mutably
319+
//~| ERROR: this argument is a mutable reference, but not used mutably
320+
async {
321+
*u += 1;
322+
}
323+
.await;
324+
}
325+
async fn foo2(&mut self, u: &mut i32, v: &mut u32) {
326+
//~^ ERROR: this argument is a mutable reference, but not used mutably
327+
async {
328+
self.a += 1;
329+
*u += 1;
330+
}
331+
.await;
332+
}
333+
}
334+
335+
impl MutSelfTrait for MutSelf {
336+
// Should not warn since it's a trait method.
337+
fn mut_self(&mut self) {}
338+
}
339+
310340
// `is_from_proc_macro` stress tests
311341
fn _empty_tup(x: &mut (())) {}
312342
fn _single_tup(x: &mut ((i32,))) {}

tests/ui/needless_pass_by_ref_mut.stderr

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,190 +14,206 @@ LL | fn foo6(s: &mut Vec<u32>) {
1414
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
1515

1616
error: this argument is a mutable reference, but not used mutably
17-
--> tests/ui/needless_pass_by_ref_mut.rs:50:29
17+
--> tests/ui/needless_pass_by_ref_mut.rs:47:12
1818
|
19-
LL | fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
20-
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
19+
LL | fn bar(&mut self) {}
20+
| ^^^^^^^^^ help: consider changing to: `&self`
2121

2222
error: this argument is a mutable reference, but not used mutably
23-
--> tests/ui/needless_pass_by_ref_mut.rs:55:31
23+
--> tests/ui/needless_pass_by_ref_mut.rs:50:29
2424
|
25-
LL | fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
26-
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
25+
LL | fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
26+
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
2727

2828
error: this argument is a mutable reference, but not used mutably
29-
--> tests/ui/needless_pass_by_ref_mut.rs:132:16
29+
--> tests/ui/needless_pass_by_ref_mut.rs:127:16
3030
|
3131
LL | async fn a1(x: &mut i32) {
3232
| ^^^^^^^^ help: consider changing to: `&i32`
3333

3434
error: this argument is a mutable reference, but not used mutably
35-
--> tests/ui/needless_pass_by_ref_mut.rs:136:16
35+
--> tests/ui/needless_pass_by_ref_mut.rs:131:16
3636
|
3737
LL | async fn a2(x: &mut i32, y: String) {
3838
| ^^^^^^^^ help: consider changing to: `&i32`
3939

4040
error: this argument is a mutable reference, but not used mutably
41-
--> tests/ui/needless_pass_by_ref_mut.rs:140:16
41+
--> tests/ui/needless_pass_by_ref_mut.rs:135:16
4242
|
4343
LL | async fn a3(x: &mut i32, y: String, z: String) {
4444
| ^^^^^^^^ help: consider changing to: `&i32`
4545

4646
error: this argument is a mutable reference, but not used mutably
47-
--> tests/ui/needless_pass_by_ref_mut.rs:144:16
47+
--> tests/ui/needless_pass_by_ref_mut.rs:139:16
4848
|
4949
LL | async fn a4(x: &mut i32, y: i32) {
5050
| ^^^^^^^^ help: consider changing to: `&i32`
5151

5252
error: this argument is a mutable reference, but not used mutably
53-
--> tests/ui/needless_pass_by_ref_mut.rs:148:24
53+
--> tests/ui/needless_pass_by_ref_mut.rs:143:24
5454
|
5555
LL | async fn a5(x: i32, y: &mut i32) {
5656
| ^^^^^^^^ help: consider changing to: `&i32`
5757

5858
error: this argument is a mutable reference, but not used mutably
59-
--> tests/ui/needless_pass_by_ref_mut.rs:152:24
59+
--> tests/ui/needless_pass_by_ref_mut.rs:147:24
6060
|
6161
LL | async fn a6(x: i32, y: &mut i32) {
6262
| ^^^^^^^^ help: consider changing to: `&i32`
6363

6464
error: this argument is a mutable reference, but not used mutably
65-
--> tests/ui/needless_pass_by_ref_mut.rs:156:32
65+
--> tests/ui/needless_pass_by_ref_mut.rs:151:32
6666
|
6767
LL | async fn a7(x: i32, y: i32, z: &mut i32) {
6868
| ^^^^^^^^ help: consider changing to: `&i32`
6969

7070
error: this argument is a mutable reference, but not used mutably
71-
--> tests/ui/needless_pass_by_ref_mut.rs:160:24
71+
--> tests/ui/needless_pass_by_ref_mut.rs:155:24
7272
|
7373
LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
7474
| ^^^^^^^^ help: consider changing to: `&i32`
7575

7676
error: this argument is a mutable reference, but not used mutably
77-
--> tests/ui/needless_pass_by_ref_mut.rs:160:45
77+
--> tests/ui/needless_pass_by_ref_mut.rs:155:45
7878
|
7979
LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
8080
| ^^^^^^^^ help: consider changing to: `&i32`
8181

8282
error: this argument is a mutable reference, but not used mutably
83-
--> tests/ui/needless_pass_by_ref_mut.rs:194:16
83+
--> tests/ui/needless_pass_by_ref_mut.rs:189:16
8484
|
8585
LL | fn cfg_warn(s: &mut u32) {}
8686
| ^^^^^^^^ help: consider changing to: `&u32`
8787
|
8888
= note: this is cfg-gated and may require further changes
8989

9090
error: this argument is a mutable reference, but not used mutably
91-
--> tests/ui/needless_pass_by_ref_mut.rs:200:20
91+
--> tests/ui/needless_pass_by_ref_mut.rs:195:20
9292
|
9393
LL | fn cfg_warn(s: &mut u32) {}
9494
| ^^^^^^^^ help: consider changing to: `&u32`
9595
|
9696
= note: this is cfg-gated and may require further changes
9797

9898
error: this argument is a mutable reference, but not used mutably
99-
--> tests/ui/needless_pass_by_ref_mut.rs:214:39
99+
--> tests/ui/needless_pass_by_ref_mut.rs:209:39
100100
|
101101
LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
102102
| ^^^^^^^^ help: consider changing to: `&u32`
103103

104104
error: this argument is a mutable reference, but not used mutably
105-
--> tests/ui/needless_pass_by_ref_mut.rs:222:26
105+
--> tests/ui/needless_pass_by_ref_mut.rs:217:26
106106
|
107107
LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
108108
| ^^^^^^^^ help: consider changing to: `&i32`
109109

110110
error: this argument is a mutable reference, but not used mutably
111-
--> tests/ui/needless_pass_by_ref_mut.rs:241:34
111+
--> tests/ui/needless_pass_by_ref_mut.rs:236:34
112112
|
113113
LL | pub async fn call_in_closure1(n: &mut str) {
114114
| ^^^^^^^^ help: consider changing to: `&str`
115115
|
116116
= warning: changing this function will impact semver compatibility
117117

118118
error: this argument is a mutable reference, but not used mutably
119-
--> tests/ui/needless_pass_by_ref_mut.rs:253:25
120-
|
121-
LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() {
122-
| ^^^^^^^^^^ help: consider changing to: `&usize`
123-
|
124-
= warning: changing this function will impact semver compatibility
125-
126-
error: this argument is a mutable reference, but not used mutably
127-
--> tests/ui/needless_pass_by_ref_mut.rs:260:20
119+
--> tests/ui/needless_pass_by_ref_mut.rs:255:20
128120
|
129121
LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
130122
| ^^^^^^^^^^ help: consider changing to: `&usize`
131123
|
132124
= warning: changing this function will impact semver compatibility
133125

134126
error: this argument is a mutable reference, but not used mutably
135-
--> tests/ui/needless_pass_by_ref_mut.rs:271:26
127+
--> tests/ui/needless_pass_by_ref_mut.rs:266:26
136128
|
137129
LL | pub async fn closure4(n: &mut usize) {
138130
| ^^^^^^^^^^ help: consider changing to: `&usize`
139131
|
140132
= warning: changing this function will impact semver compatibility
141133

142134
error: this argument is a mutable reference, but not used mutably
143-
--> tests/ui/needless_pass_by_ref_mut.rs:311:18
135+
--> tests/ui/needless_pass_by_ref_mut.rs:315:12
136+
|
137+
LL | fn bar(&mut self) {}
138+
| ^^^^^^^^^ help: consider changing to: `&self`
139+
140+
error: this argument is a mutable reference, but not used mutably
141+
--> tests/ui/needless_pass_by_ref_mut.rs:317:18
142+
|
143+
LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) {
144+
| ^^^^^^^^^ help: consider changing to: `&self`
145+
146+
error: this argument is a mutable reference, but not used mutably
147+
--> tests/ui/needless_pass_by_ref_mut.rs:317:45
148+
|
149+
LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) {
150+
| ^^^^^^^^ help: consider changing to: `&u32`
151+
152+
error: this argument is a mutable reference, but not used mutably
153+
--> tests/ui/needless_pass_by_ref_mut.rs:325:46
154+
|
155+
LL | async fn foo2(&mut self, u: &mut i32, v: &mut u32) {
156+
| ^^^^^^^^ help: consider changing to: `&u32`
157+
158+
error: this argument is a mutable reference, but not used mutably
159+
--> tests/ui/needless_pass_by_ref_mut.rs:341:18
144160
|
145161
LL | fn _empty_tup(x: &mut (())) {}
146162
| ^^^^^^^^^ help: consider changing to: `&()`
147163

148164
error: this argument is a mutable reference, but not used mutably
149-
--> tests/ui/needless_pass_by_ref_mut.rs:312:19
165+
--> tests/ui/needless_pass_by_ref_mut.rs:342:19
150166
|
151167
LL | fn _single_tup(x: &mut ((i32,))) {}
152168
| ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)`
153169

154170
error: this argument is a mutable reference, but not used mutably
155-
--> tests/ui/needless_pass_by_ref_mut.rs:313:18
171+
--> tests/ui/needless_pass_by_ref_mut.rs:343:18
156172
|
157173
LL | fn _multi_tup(x: &mut ((i32, u32))) {}
158174
| ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)`
159175

160176
error: this argument is a mutable reference, but not used mutably
161-
--> tests/ui/needless_pass_by_ref_mut.rs:314:11
177+
--> tests/ui/needless_pass_by_ref_mut.rs:344:11
162178
|
163179
LL | fn _fn(x: &mut (fn())) {}
164180
| ^^^^^^^^^^^ help: consider changing to: `&fn()`
165181

166182
error: this argument is a mutable reference, but not used mutably
167-
--> tests/ui/needless_pass_by_ref_mut.rs:316:23
183+
--> tests/ui/needless_pass_by_ref_mut.rs:346:23
168184
|
169185
LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {}
170186
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()`
171187

172188
error: this argument is a mutable reference, but not used mutably
173-
--> tests/ui/needless_pass_by_ref_mut.rs:317:20
189+
--> tests/ui/needless_pass_by_ref_mut.rs:347:20
174190
|
175191
LL | fn _extern_c_fn(x: &mut extern "C" fn()) {}
176192
| ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()`
177193

178194
error: this argument is a mutable reference, but not used mutably
179-
--> tests/ui/needless_pass_by_ref_mut.rs:318:18
195+
--> tests/ui/needless_pass_by_ref_mut.rs:348:18
180196
|
181197
LL | fn _unsafe_fn(x: &mut unsafe fn()) {}
182198
| ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()`
183199

184200
error: this argument is a mutable reference, but not used mutably
185-
--> tests/ui/needless_pass_by_ref_mut.rs:319:25
201+
--> tests/ui/needless_pass_by_ref_mut.rs:349:25
186202
|
187203
LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {}
188204
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()`
189205

190206
error: this argument is a mutable reference, but not used mutably
191-
--> tests/ui/needless_pass_by_ref_mut.rs:320:20
207+
--> tests/ui/needless_pass_by_ref_mut.rs:350:20
192208
|
193209
LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {}
194210
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)`
195211

196212
error: this argument is a mutable reference, but not used mutably
197-
--> tests/ui/needless_pass_by_ref_mut.rs:321:20
213+
--> tests/ui/needless_pass_by_ref_mut.rs:351:20
198214
|
199215
LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {}
200216
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)`
201217

202-
error: aborting due to 31 previous errors
218+
error: aborting due to 34 previous errors
203219

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// If both `inner_async3` and `inner_async4` are present, aliases are declared after
2+
// they're used in `inner_async4` for some reasons... This test ensures that no
3+
// only `v` is marked as not used mutably in `inner_async4`.
4+
5+
#![allow(clippy::redundant_closure_call)]
6+
#![warn(clippy::needless_pass_by_ref_mut)]
7+
8+
pub async fn inner_async3(x: &i32, y: &mut u32) {
9+
//~^ ERROR: this argument is a mutable reference, but not used mutably
10+
async {
11+
*y += 1;
12+
}
13+
.await;
14+
}
15+
16+
pub async fn inner_async4(u: &mut i32, v: &u32) {
17+
//~^ ERROR: this argument is a mutable reference, but not used mutably
18+
async {
19+
*u += 1;
20+
}
21+
.await;
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)