Lint against needless uses of collect()#3109
Conversation
oli-obk
left a comment
There was a problem hiding this comment.
You found a case of this in clippy! https://travis-ci.org/rust-lang-nursery/rust-clippy/jobs/422867441#L1079
Can you fix it?
| 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.
Is that really the best suggestion? Feels a little hacky
There was a problem hiding this comment.
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.
Hah, you're right. My mistake. I agree, .next().is_none() feels cleaner.
| --> $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.
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.
| 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.
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!)
| 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.
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. |
killercup
left a comment
There was a problem hiding this comment.
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