-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lint against needless uses of collect()
#3109
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You found a case of this in clippy! https://travis-ci.org/rust-lang-nursery/rust-clippy/jobs/422867441#L1079
Can you fix it?
clippy_lints/src/loops.rs
Outdated
fn generate_needless_collect_is_empty_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { | ||
if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { | ||
let iter = snippet(cx, args[0].span, "??"); | ||
return format!("{}.any(|_| true)", iter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that really the best suggestion? Feels a little hacky
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it even correct? If there is any item, is_empty should return false, right?
I'd suggest .next().is_none()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hah, you're right. My mistake. I agree, .next().is_none()
feels cleaner.
tests/ui/needless_collect.stderr
Outdated
--> $DIR/needless_collect.rs:5:15 | ||
| | ||
5 | let len = sample.iter().collect::<Vec<_>>().len(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing with: `sample.iter().count()` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be awesome if you could limit the span to only cover the collect().len() here (and similarly below) and suggest to replace only that with .count(). Iterator chains can get quite long.
clippy_lints/src/loops.rs
Outdated
if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node { | ||
if chain_method.ident.name == "collect" && match_trait_method(cx, &args[0], &paths::ITERATOR) { | ||
if method.ident.name == "len" { | ||
span_lint_and_sugg( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How confident are you that these suggestions can be automatically applied? When can they not be auto-applied? If you can use span_suggestion_with_applicability here, rustfix can pick it up :)
(Yes I know most clippy lints don't do that right now, but maybe we can start doing it for new ones!)
clippy_lints/src/loops.rs
Outdated
fn generate_needless_collect_is_empty_sugg<'a, 'tcx>(collect_expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>) -> String { | ||
if let ExprKind::MethodCall(_, _, ref args) = collect_expr.node { | ||
let iter = snippet(cx, args[0].span, "??"); | ||
return format!("{}.any(|_| true)", iter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it even correct? If there is any item, is_empty should return false, right?
I'd suggest .next().is_none()
|
Looks like it. Ideally I think using |
Sounds good for a start. Using other lists or maps should be fine, too, but sets have observably different properties. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except for that stray needless_collect
file
You might be able to also get rid of some of the highly indented code by using the if_chain! macro, but that can also be done in separate PR later
Handles cases of `.collect().len()`, `.collect().is_empty()`, and `.collect().contains()`. This lint is intended to be generic enough to be added to at a later time with other similar patterns that could be optimized. Closes rust-lang#3034
d88eb48
to
f7d2aee
Compare
Rebased and fixed rustup issues. Also swapped out some nesting for |
Handles cases of
.collect().len()
,.collect().is_empty()
, and.collect().contains()
. This lint is intended to be generic enough tobe added to at a later time with other similar patterns that could be
optimized.
Closes #3034