Skip to content

Commit 918e776

Browse files
committed
Move lint to methods pass
This gives us things like checking if we are in a macro
1 parent 7e3e245 commit 918e776

File tree

6 files changed

+56
-45
lines changed

6 files changed

+56
-45
lines changed

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
320320
crate::manual_unwrap_or_default::MANUAL_UNWRAP_OR_DEFAULT_INFO,
321321
crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO,
322322
crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO,
323-
crate::map_with_unused_argument_over_ranges::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES_INFO,
324323
crate::match_result_ok::MATCH_RESULT_OK_INFO,
325324
crate::matches::COLLAPSIBLE_MATCH_INFO,
326325
crate::matches::INFALLIBLE_DESTRUCTURING_MATCH_INFO,
@@ -419,6 +418,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
419418
crate::methods::MAP_FLATTEN_INFO,
420419
crate::methods::MAP_IDENTITY_INFO,
421420
crate::methods::MAP_UNWRAP_OR_INFO,
421+
crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES_INFO,
422422
crate::methods::MUT_MUTEX_LOCK_INFO,
423423
crate::methods::NAIVE_BYTECOUNT_INFO,
424424
crate::methods::NEEDLESS_CHARACTER_ITERATION_INFO,

clippy_lints/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ mod manual_string_new;
217217
mod manual_strip;
218218
mod manual_unwrap_or_default;
219219
mod map_unit_fn;
220-
mod map_with_unused_argument_over_ranges;
221220
mod match_result_ok;
222221
mod matches;
223222
mod mem_replace;
@@ -1175,9 +1174,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
11751174
store.register_late_pass(move |_| Box::new(string_patterns::StringPatterns::new(msrv())));
11761175
store.register_early_pass(|| Box::new(field_scoped_visibility_modifiers::FieldScopedVisibilityModifiers));
11771176
store.register_late_pass(|_| Box::new(set_contains_or_insert::HashsetInsertAfterContains));
1178-
store.register_late_pass(move |_| {
1179-
Box::new(map_with_unused_argument_over_ranges::MapWithUnusedArgumentOverRanges::new(msrv()))
1180-
});
11811177
// add lints here, do not remove this comment, it's used in `new_lint`
11821178
}
11831179

clippy_lints/src/map_with_unused_argument_over_ranges.rs renamed to clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -90,32 +90,29 @@ fn extract_count_with_applicability(
9090
None
9191
}
9292

93-
impl LateLintPass<'_> for MapWithUnusedArgumentOverRanges {
94-
fn check_expr(&mut self, cx: &LateContext<'_>, ex: &Expr<'_>) {
95-
if !self.msrv.meets(msrvs::REPEAT_WITH) {
96-
return;
97-
}
98-
let mut applicability = Applicability::MaybeIncorrect;
99-
if let ExprKind::MethodCall(path, receiver, [map_arg_expr], _call_span) = ex.kind
100-
&& path.ident.name == rustc_span::sym::map
101-
&& let Some(range) = higher::Range::hir(receiver)
102-
&& let ExprKind::Closure(Closure { body, .. }) = map_arg_expr.kind
103-
&& let Body { params: [param], .. } = cx.tcx.hir().body(*body)
104-
&& matches!(param.pat.kind, PatKind::Wild)
105-
&& let Some(count) = extract_count_with_applicability(cx, range, &mut applicability)
106-
{
107-
let snippet = snippet_with_applicability(cx, map_arg_expr.span, "|| { ... }", &mut applicability)
108-
.replacen("|_|", "||", 1);
109-
span_lint_and_sugg(
110-
cx,
111-
MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
112-
ex.span,
113-
"map of a trivial closure (not dependent on parameter) over a range",
114-
"use",
115-
format!("std::iter::repeat_with({snippet}).take({count})"),
116-
applicability,
117-
);
118-
}
93+
pub(super) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>, msrv: &Msrv) {
94+
if !msrv.meets(msrvs::REPEAT_WITH) {
95+
return;
96+
}
97+
let mut applicability = Applicability::MaybeIncorrect;
98+
if let ExprKind::MethodCall(path, receiver, [map_arg_expr], _call_span) = ex.kind
99+
&& path.ident.name == rustc_span::sym::map
100+
&& let Some(range) = higher::Range::hir(receiver)
101+
&& let ExprKind::Closure(Closure { body, .. }) = map_arg_expr.kind
102+
&& let Body { params: [param], .. } = cx.tcx.hir().body(*body)
103+
&& matches!(param.pat.kind, PatKind::Wild)
104+
&& let Some(count) = extract_count_with_applicability(cx, range, &mut applicability)
105+
{
106+
let snippet = snippet_with_applicability(cx, map_arg_expr.span, "|| { ... }", &mut applicability)
107+
.replacen("|_|", "||", 1);
108+
span_lint_and_sugg(
109+
cx,
110+
MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
111+
ex.span,
112+
"map of a trivial closure (not dependent on parameter) over a range",
113+
"use",
114+
format!("std::iter::repeat_with({snippet}).take({count})"),
115+
applicability,
116+
);
119117
}
120-
extract_msrv_attr!(LateContext);
121118
}

clippy_lints/src/methods/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ mod map_err_ignore;
6666
mod map_flatten;
6767
mod map_identity;
6868
mod map_unwrap_or;
69+
mod map_with_unused_argument_over_ranges;
6970
mod mut_mutex_lock;
7071
mod needless_character_iteration;
7172
mod needless_collect;
@@ -4127,6 +4128,32 @@ declare_clippy_lint! {
41274128
"use of `map` returning the original item"
41284129
}
41294130

4131+
declare_clippy_lint! {
4132+
/// ### What it does
4133+
///
4134+
/// Checks for `Iterator::map` over ranges without using the parameter which
4135+
/// could be more clearly expressed using `std::iter::repeat_with(...).take(...)`.
4136+
///
4137+
/// ### Why is this bad?
4138+
///
4139+
/// It expresses the intent more clearly to `take` the correct number of times
4140+
/// from a generating function than to apply a closure to each number in a
4141+
/// range only to discard them.
4142+
///
4143+
/// ### Example
4144+
/// ```no_run
4145+
/// let random_numbers : Vec<_> = (0..10).map(|_| { 3 + 1 }).collect();
4146+
/// ```
4147+
/// Use instead:
4148+
/// ```no_run
4149+
/// let f : Vec<_> = std::iter::repeat_with(|| { 3 + 1 }).take(10).collect();
4150+
/// ```
4151+
#[clippy::version = "1.81.0"]
4152+
pub MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
4153+
style,
4154+
"map of a trivial closure (not dependent on parameter) over a range"
4155+
}
4156+
41304157
pub struct Methods {
41314158
avoid_breaking_exported_api: bool,
41324159
msrv: Msrv,
@@ -4294,6 +4321,7 @@ impl_lint_pass!(Methods => [
42944321
NEEDLESS_CHARACTER_ITERATION,
42954322
MANUAL_INSPECT,
42964323
UNNECESSARY_MIN_OR_MAX,
4324+
MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
42974325
]);
42984326

42994327
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4769,6 +4797,7 @@ impl Methods {
47694797
if name == "map" {
47704798
unused_enumerate_index::check(cx, expr, recv, m_arg);
47714799
map_clone::check(cx, expr, recv, m_arg, &self.msrv);
4800+
map_with_unused_argument_over_ranges::check(cx, expr, recv, m_arg, &self.msrv);
47724801
match method_call(recv) {
47734802
Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => {
47744803
iter_kv_map::check(cx, map_name, expr, recv2, m_arg, &self.msrv);

tests/ui/map_with_unused_argument_over_ranges.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn do_something_interesting(x: usize, y: usize) -> usize {
1111

1212
macro_rules! gen {
1313
() => {
14-
std::iter::repeat_with(|| do_something()).take(10);
14+
(0..10).map(|_| do_something());
1515
};
1616
}
1717

tests/ui/map_with_unused_argument_over_ranges.stderr

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,6 @@ error: map of a trivial closure (not dependent on parameter) over a range
7878
LL | (2..=upper_fn()).map(|_| do_something());
7979
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::iter::repeat_with(|| do_something()).take(upper_fn() + 3)`
8080

81-
error: map of a trivial closure (not dependent on parameter) over a range
82-
--> tests/ui/map_with_unused_argument_over_ranges.rs:14:9
83-
|
84-
LL | (0..10).map(|_| do_something());
85-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::iter::repeat_with(|| do_something()).take(10)`
86-
...
87-
LL | gen!();
88-
| ------ in this macro invocation
89-
|
90-
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
91-
9281
error: map of a trivial closure (not dependent on parameter) over a range
9382
--> tests/ui/map_with_unused_argument_over_ranges.rs:41:5
9483
|
@@ -101,5 +90,5 @@ error: map of a trivial closure (not dependent on parameter) over a range
10190
LL | (0..10).map(|_| do_something());
10291
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::iter::repeat_with(|| do_something()).take(10)`
10392

104-
error: aborting due to 14 previous errors
93+
error: aborting due to 13 previous errors
10594

0 commit comments

Comments
 (0)