Skip to content

Commit 10d29eb

Browse files
committed
find expansions more efficiently
1 parent 0165aa1 commit 10d29eb

File tree

4 files changed

+44
-22
lines changed

4 files changed

+44
-22
lines changed

clippy_lints/src/useless_conversion.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ declare_clippy_lint! {
4141
#[derive(Default)]
4242
pub struct UselessConversion {
4343
try_desugar_arm: Vec<HirId>,
44+
expn_depth: u32,
4445
}
4546

4647
impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]);
@@ -103,21 +104,11 @@ fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -
103104
(expr, depth)
104105
}
105106

106-
/// Checks if the given `expr` is an argument of a macro invocation.
107-
/// This is a slow-ish operation, so consider calling this late
108-
/// to avoid slowing down the lint in the happy path when not emitting a warning
109-
fn is_macro_argument(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
110-
if let Some(parent) = get_parent_expr(cx, expr) {
111-
parent.span.from_expansion() || is_macro_argument(cx, parent)
112-
} else {
113-
false
114-
}
115-
}
116-
117107
#[expect(clippy::too_many_lines)]
118108
impl<'tcx> LateLintPass<'tcx> for UselessConversion {
119109
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
120110
if e.span.from_expansion() {
111+
self.expn_depth += 1;
121112
return;
122113
}
123114

@@ -186,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
186177
&& let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos))
187178
&& let ty::Param(param) = into_iter_param.kind()
188179
&& let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index)
189-
&& !is_macro_argument(cx, e)
180+
&& self.expn_depth == 0
190181
{
191182
// Get the "innermost" `.into_iter()` call, e.g. given this expression:
192183
// `foo.into_iter().into_iter()`
@@ -322,5 +313,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
322313
if Some(&e.hir_id) == self.try_desugar_arm.last() {
323314
self.try_desugar_arm.pop();
324315
}
316+
if e.span.from_expansion() {
317+
self.expn_depth -= 1;
318+
}
325319
}
326320
}

tests/ui/useless_conversion.fixed

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ fn main() {
155155
let _ = vec![s4, s4, s4].into_iter();
156156
}
157157

158+
#[allow(dead_code)]
159+
fn issue11065_fp() {
160+
use std::option::IntoIter;
161+
fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
162+
163+
macro_rules! x {
164+
($e:expr) => {
165+
takes_into_iter($e);
166+
let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
167+
};
168+
}
169+
x!(Some(5).into_iter());
170+
}
171+
158172
#[allow(dead_code)]
159173
fn explicit_into_iter_fn_arg() {
160174
fn a<T>(_: T) {}

tests/ui/useless_conversion.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ fn main() {
155155
let _ = vec![s4, s4, s4].into_iter().into_iter();
156156
}
157157

158+
#[allow(dead_code)]
159+
fn issue11065_fp() {
160+
use std::option::IntoIter;
161+
fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
162+
163+
macro_rules! x {
164+
($e:expr) => {
165+
takes_into_iter($e);
166+
let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
167+
};
168+
}
169+
x!(Some(5).into_iter());
170+
}
171+
158172
#[allow(dead_code)]
159173
fn explicit_into_iter_fn_arg() {
160174
fn a<T>(_: T) {}

tests/ui/useless_conversion.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,61 +119,61 @@ LL | let _ = vec![s4, s4, s4].into_iter().into_iter();
119119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
120120

121121
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
122-
--> $DIR/useless_conversion.rs:171:7
122+
--> $DIR/useless_conversion.rs:185:7
123123
|
124124
LL | b(vec![1, 2].into_iter());
125125
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
126126
|
127127
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
128-
--> $DIR/useless_conversion.rs:161:13
128+
--> $DIR/useless_conversion.rs:175:13
129129
|
130130
LL | fn b<T: IntoIterator<Item = i32>>(_: T) {}
131131
| ^^^^^^^^^^^^^^^^^^^^^^^^
132132

133133
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
134-
--> $DIR/useless_conversion.rs:172:7
134+
--> $DIR/useless_conversion.rs:186:7
135135
|
136136
LL | c(vec![1, 2].into_iter());
137137
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
138138
|
139139
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
140-
--> $DIR/useless_conversion.rs:162:18
140+
--> $DIR/useless_conversion.rs:176:18
141141
|
142142
LL | fn c(_: impl IntoIterator<Item = i32>) {}
143143
| ^^^^^^^^^^^^^^^^^^^^^^^^
144144

145145
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
146-
--> $DIR/useless_conversion.rs:173:7
146+
--> $DIR/useless_conversion.rs:187:7
147147
|
148148
LL | d(vec![1, 2].into_iter());
149149
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
150150
|
151151
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
152-
--> $DIR/useless_conversion.rs:165:12
152+
--> $DIR/useless_conversion.rs:179:12
153153
|
154154
LL | T: IntoIterator<Item = i32>,
155155
| ^^^^^^^^^^^^^^^^^^^^^^^^
156156

157157
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
158-
--> $DIR/useless_conversion.rs:176:7
158+
--> $DIR/useless_conversion.rs:190:7
159159
|
160160
LL | b(vec![1, 2].into_iter().into_iter());
161161
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
162162
|
163163
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
164-
--> $DIR/useless_conversion.rs:161:13
164+
--> $DIR/useless_conversion.rs:175:13
165165
|
166166
LL | fn b<T: IntoIterator<Item = i32>>(_: T) {}
167167
| ^^^^^^^^^^^^^^^^^^^^^^^^
168168

169169
error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
170-
--> $DIR/useless_conversion.rs:177:7
170+
--> $DIR/useless_conversion.rs:191:7
171171
|
172172
LL | b(vec![1, 2].into_iter().into_iter().into_iter());
173173
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
174174
|
175175
note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
176-
--> $DIR/useless_conversion.rs:161:13
176+
--> $DIR/useless_conversion.rs:175:13
177177
|
178178
LL | fn b<T: IntoIterator<Item = i32>>(_: T) {}
179179
| ^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)