Auto merge of #11070 - y21:issue11065, r=flip1995

[`useless_conversion`]: only lint on paths to fn items and fix FP in macro

Fixes #11065 (which is actually two issues: an ICE and a false positive)

It now makes sure that the function call path points to a function-like item (and not e.g. a `const` like in the linked issue), so that calling `TyCtxt::fn_sig` later in the lint does not ICE (fixes https://github.com/rust-lang/rust-clippy/issues/11065#issuecomment-1616836099).
It *also* makes sure that the expression is not part of a macro call (fixes https://github.com/rust-lang/rust-clippy/issues/11065#issuecomment-1616919639). ~~I'm not sure if there's a better way to check this other than to walk the parent expr chain and see if any of them are expansions.~~ (edit: it doesn't do this anymore)

changelog: [`useless_conversion`]: fix ICE when call receiver is a non-fn item
changelog: [`useless_conversion`]: don't lint if argument is a macro argument (fixes a FP)

r? `@llogiq` (reviewed #10814, which introduced these issues)
This commit is contained in:
bors 2023-08-17 14:41:46 +00:00
commit 701e77c87f
5 changed files with 72 additions and 13 deletions

View file

@ -0,0 +1,19 @@
#![warn(clippy::useless_conversion)]
use std::iter::FromIterator;
use std::option::IntoIter as OptionIter;
fn eq<T: Eq>(a: T, b: T) -> bool {
a == b
}
macro_rules! tests {
($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
const C: $ty = $expr;
assert!(eq(C($($test),*), $expr($($test),*)));
})+})
}
tests! {
FromIterator::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
}

View file

@ -153,6 +153,20 @@ fn main() {
let _ = vec![s4, s4, s4].into_iter();
}
#[allow(dead_code)]
fn issue11065_fp() {
use std::option::IntoIter;
fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
macro_rules! x {
($e:expr) => {
takes_into_iter($e);
let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
};
}
x!(Some(5).into_iter());
}
#[allow(dead_code)]
fn explicit_into_iter_fn_arg() {
fn a<T>(_: T) {}

View file

@ -153,6 +153,20 @@ fn main() {
let _ = vec![s4, s4, s4].into_iter().into_iter();
}
#[allow(dead_code)]
fn issue11065_fp() {
use std::option::IntoIter;
fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
macro_rules! x {
($e:expr) => {
takes_into_iter($e);
let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
};
}
x!(Some(5).into_iter());
}
#[allow(dead_code)]
fn explicit_into_iter_fn_arg() {
fn a<T>(_: T) {}

View file

@ -119,61 +119,61 @@ LL | let _ = vec![s4, s4, s4].into_iter().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
--> $DIR/useless_conversion.rs:169:7
--> $DIR/useless_conversion.rs:183:7
|
LL | b(vec![1, 2].into_iter());
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
|
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
--> $DIR/useless_conversion.rs:159:13
--> $DIR/useless_conversion.rs:173:13
|
LL | fn b<T: IntoIterator<Item = i32>>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
--> $DIR/useless_conversion.rs:170:7
--> $DIR/useless_conversion.rs:184:7
|
LL | c(vec![1, 2].into_iter());
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
|
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
--> $DIR/useless_conversion.rs:160:18
--> $DIR/useless_conversion.rs:174:18
|
LL | fn c(_: impl IntoIterator<Item = i32>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
--> $DIR/useless_conversion.rs:171:7
--> $DIR/useless_conversion.rs:185:7
|
LL | d(vec![1, 2].into_iter());
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
|
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
--> $DIR/useless_conversion.rs:163:12
--> $DIR/useless_conversion.rs:177:12
|
LL | T: IntoIterator<Item = i32>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
--> $DIR/useless_conversion.rs:174:7
--> $DIR/useless_conversion.rs:188:7
|
LL | b(vec![1, 2].into_iter().into_iter());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
|
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
--> $DIR/useless_conversion.rs:159:13
--> $DIR/useless_conversion.rs:173:13
|
LL | fn b<T: IntoIterator<Item = i32>>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
--> $DIR/useless_conversion.rs:175:7
--> $DIR/useless_conversion.rs:189:7
|
LL | b(vec![1, 2].into_iter().into_iter().into_iter());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
|
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
--> $DIR/useless_conversion.rs:159:13
--> $DIR/useless_conversion.rs:173:13
|
LL | fn b<T: IntoIterator<Item = i32>>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^