Skip to content

Commit 4c24655

Browse files
author
immersum
committed
Fix ptr_arg suggests changes when it's actually better not to bother
changelog: fix false positive: [`ptr_arg`] no longer triggers with underscore binding to `&mut` argument Fixes #13489 Fixes #13728
1 parent 425d761 commit 4c24655

File tree

3 files changed

+137
-3
lines changed

3 files changed

+137
-3
lines changed

clippy_lints/src/ptr.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,12 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[
584584
Some((Node::Stmt(_), _)) => (),
585585
Some((Node::LetStmt(l), _)) => {
586586
// Only trace simple bindings. e.g `let x = y;`
587-
if let PatKind::Binding(BindingMode::NONE, id, _, None) = l.pat.kind {
587+
if let PatKind::Binding(BindingMode::NONE, id, ident, None) = l.pat.kind
588+
// Let's not lint for the current parameter. The user may still intend to mutate
589+
// the referenced value behind the parameter through this local let binding with
590+
// the underscore being temporary.
591+
&& !(ident.name.as_str().starts_with('_') && args.mutability() == Mutability::Mut)
592+
{
588593
self.bindings.insert(id, args_idx);
589594
} else {
590595
set_skip_flag();
@@ -650,7 +655,12 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[
650655
.filter_map(|(i, arg)| {
651656
let param = &body.params[arg.idx];
652657
match param.pat.kind {
653-
PatKind::Binding(BindingMode::NONE, id, _, None) if !is_lint_allowed(cx, PTR_ARG, param.hir_id) => {
658+
PatKind::Binding(BindingMode::NONE, id, ident, None)
659+
// Let's not lint for the current parameter. The user may still intend to mutate
660+
// the referenced value behind the parameter with the underscore being temporary.
661+
if !(ident.name.as_str().starts_with('_') && arg.mutability() == Mutability::Mut
662+
|| is_lint_allowed(cx, PTR_ARG, param.hir_id)) =>
663+
{
654664
Some((id, i))
655665
},
656666
_ => {

tests/ui/ptr_arg.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,91 @@ mod issue_13308 {
352352
h2(String::new(), v2);
353353
}
354354
}
355+
356+
mod issue_13489 {
357+
// This is a no-lint from now on.
358+
fn foo(_x: &mut Vec<i32>) {
359+
todo!();
360+
}
361+
362+
// But this still gives us a lint.
363+
fn foo_used(x: &mut Vec<i32>) {
364+
//~^ ptr_arg
365+
366+
todo!();
367+
}
368+
369+
// This is also a no-lint from now on.
370+
fn foo_local(x: &mut Vec<i32>) {
371+
let _y = x;
372+
373+
todo!();
374+
}
375+
376+
// But this still gives us a lint.
377+
fn foo_local_used(x: &mut Vec<i32>) {
378+
//~^ ptr_arg
379+
380+
let y = x;
381+
382+
todo!();
383+
}
384+
385+
// This only lints once from now on.
386+
fn foofoo(_x: &mut Vec<i32>, y: &mut String) {
387+
//~^ ptr_arg
388+
389+
todo!();
390+
}
391+
392+
// And this is also a no-lint from now on.
393+
fn foofoo_local(_x: &mut Vec<i32>, y: &mut String) {
394+
let _z = y;
395+
396+
todo!();
397+
}
398+
}
399+
400+
mod issue_13728 {
401+
// This is a no-lint from now on.
402+
fn bar(_x: &mut Vec<u32>) {
403+
todo!()
404+
}
405+
406+
// But this still gives us a lint.
407+
fn bar_used(x: &mut Vec<u32>) {
408+
//~^ ptr_arg
409+
410+
todo!()
411+
}
412+
413+
// This is also a no-lint from now on.
414+
fn bar_local(x: &mut Vec<u32>) {
415+
let _y = x;
416+
417+
todo!()
418+
}
419+
420+
// But this still gives us a lint.
421+
fn bar_local_used(x: &mut Vec<u32>) {
422+
//~^ ptr_arg
423+
424+
let y = x;
425+
426+
todo!()
427+
}
428+
429+
// This only lints once from now on.
430+
fn barbar(_x: &mut Vec<u32>, y: &mut String) {
431+
//~^ ptr_arg
432+
433+
todo!()
434+
}
435+
436+
// And this is also a no-lint from now on.
437+
fn barbar_local(_x: &mut Vec<u32>, y: &mut String) {
438+
let _z = y;
439+
440+
todo!()
441+
}
442+
}

tests/ui/ptr_arg.stderr

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,42 @@ error: writing `&String` instead of `&str` involves a new object where a slice w
231231
LL | fn good(v1: &String, v2: &String) {
232232
| ^^^^^^^ help: change this to: `&str`
233233

234+
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
235+
--> tests/ui/ptr_arg.rs:363:20
236+
|
237+
LL | fn foo_used(x: &mut Vec<i32>) {
238+
| ^^^^^^^^^^^^^ help: change this to: `&mut [i32]`
239+
240+
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
241+
--> tests/ui/ptr_arg.rs:377:26
242+
|
243+
LL | fn foo_local_used(x: &mut Vec<i32>) {
244+
| ^^^^^^^^^^^^^ help: change this to: `&mut [i32]`
245+
246+
error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
247+
--> tests/ui/ptr_arg.rs:386:37
248+
|
249+
LL | fn foofoo(_x: &mut Vec<i32>, y: &mut String) {
250+
| ^^^^^^^^^^^ help: change this to: `&mut str`
251+
252+
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
253+
--> tests/ui/ptr_arg.rs:407:20
254+
|
255+
LL | fn bar_used(x: &mut Vec<u32>) {
256+
| ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
257+
258+
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
259+
--> tests/ui/ptr_arg.rs:421:26
260+
|
261+
LL | fn bar_local_used(x: &mut Vec<u32>) {
262+
| ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
263+
264+
error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
265+
--> tests/ui/ptr_arg.rs:430:37
266+
|
267+
LL | fn barbar(_x: &mut Vec<u32>, y: &mut String) {
268+
| ^^^^^^^^^^^ help: change this to: `&mut str`
269+
234270
error: lifetime flowing from input to output with different syntax can be confusing
235271
--> tests/ui/ptr_arg.rs:314:36
236272
|
@@ -247,5 +283,5 @@ help: one option is to consistently use `'a`
247283
LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &'a str {
248284
| ++
249285

250-
error: aborting due to 27 previous errors
286+
error: aborting due to 33 previous errors
251287

0 commit comments

Comments
 (0)