Auto merge of #12843 - mdm:fix-unnecessary-to-owned-println-interaction, r=y21

Fix `unnecessary_to_owned` interaction with macro expansion

fixes #12821

In the case of an unnecessary `.iter().cloned()`, the lint `unnecessary_to_owned` might suggest to remove the `&` from references without checking if such references are inside a macro expansion. This can lead to unexpected behavior or even broken code if the lint suggestion is applied blindly. See issue #12821 for an example.

This PR checks if such references are inside macro expansions and skips this part of the lint suggestion in these cases.

changelog: [`unnecessary_to_owned`]: Don't suggest to remove `&` inside macro expansion
This commit is contained in:
bors 2024-05-27 14:26:50 +00:00
commit 7e4c1ae0b6
6 changed files with 117 additions and 19 deletions

View file

@ -170,3 +170,32 @@ fn check_mut_iteratee_and_modify_inner_variable() {
}
}
}
mod issue_12821 {
fn foo() {
let v: Vec<_> = "hello".chars().collect();
for c in v.iter() {
//~^ ERROR: unnecessary use of `cloned`
println!("{c}"); // should not suggest to remove `&`
}
}
fn bar() {
let v: Vec<_> = "hello".chars().collect();
for c in v.iter() {
//~^ ERROR: unnecessary use of `cloned`
let ref_c = c; //~ HELP: remove any references to the binding
println!("{ref_c}");
}
}
fn baz() {
let v: Vec<_> = "hello".chars().enumerate().collect();
for (i, c) in v.iter() {
//~^ ERROR: unnecessary use of `cloned`
let ref_c = c; //~ HELP: remove any references to the binding
let ref_i = i;
println!("{i} {ref_c}"); // should not suggest to remove `&` from `i`
}
}
}

View file

@ -170,3 +170,32 @@ fn check_mut_iteratee_and_modify_inner_variable() {
}
}
}
mod issue_12821 {
fn foo() {
let v: Vec<_> = "hello".chars().collect();
for c in v.iter().cloned() {
//~^ ERROR: unnecessary use of `cloned`
println!("{c}"); // should not suggest to remove `&`
}
}
fn bar() {
let v: Vec<_> = "hello".chars().collect();
for c in v.iter().cloned() {
//~^ ERROR: unnecessary use of `cloned`
let ref_c = &c; //~ HELP: remove any references to the binding
println!("{ref_c}");
}
}
fn baz() {
let v: Vec<_> = "hello".chars().enumerate().collect();
for (i, c) in v.iter().cloned() {
//~^ ERROR: unnecessary use of `cloned`
let ref_c = &c; //~ HELP: remove any references to the binding
let ref_i = &i;
println!("{i} {ref_c}"); // should not suggest to remove `&` from `i`
}
}
}

View file

@ -10,7 +10,7 @@ help: use
|
LL | for (t, path) in files {
| ~~~~~
help: remove this `&`
help: remove any references to the binding
|
LL - let other = match get_file_path(&t) {
LL + let other = match get_file_path(t) {
@ -26,11 +26,49 @@ help: use
|
LL | for (t, path) in files.iter() {
| ~~~~~~~~~~~~
help: remove this `&`
help: remove any references to the binding
|
LL - let other = match get_file_path(&t) {
LL + let other = match get_file_path(t) {
|
error: aborting due to 2 previous errors
error: unnecessary use of `cloned`
--> tests/ui/unnecessary_iter_cloned.rs:177:18
|
LL | for c in v.iter().cloned() {
| ^^^^^^^^^^^^^^^^^ help: use: `v.iter()`
error: unnecessary use of `cloned`
--> tests/ui/unnecessary_iter_cloned.rs:185:18
|
LL | for c in v.iter().cloned() {
| ^^^^^^^^^^^^^^^^^
|
help: use
|
LL | for c in v.iter() {
| ~~~~~~~~
help: remove any references to the binding
|
LL - let ref_c = &c;
LL + let ref_c = c;
|
error: unnecessary use of `cloned`
--> tests/ui/unnecessary_iter_cloned.rs:194:23
|
LL | for (i, c) in v.iter().cloned() {
| ^^^^^^^^^^^^^^^^^
|
help: use
|
LL | for (i, c) in v.iter() {
| ~~~~~~~~
help: remove any references to the binding
|
LL ~ let ref_c = c;
LL ~ let ref_i = i;
|
error: aborting due to 5 previous errors

View file

@ -487,7 +487,7 @@ help: use
|
LL | for t in file_types {
| ~~~~~~~~~~
help: remove this `&`
help: remove any references to the binding
|
LL - let path = match get_file_path(&t) {
LL + let path = match get_file_path(t) {