From 888657e09a2133fc105382136f61915086144e3f Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Sat, 8 Aug 2020 18:13:43 +0200 Subject: [PATCH] Fix ICE in `loops` module --- clippy_lints/src/loops.rs | 20 ++++++++++---------- tests/ui/crashes/ice-5872.rs | 5 +++++ tests/ui/crashes/ice-5872.stderr | 10 ++++++++++ tests/ui/needless_collect.fixed | 4 ++-- tests/ui/needless_collect.rs | 2 +- tests/ui/needless_collect.stderr | 4 ++-- 6 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 tests/ui/crashes/ice-5872.rs create mode 100644 tests/ui/crashes/ice-5872.stderr diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6359c20040c7..1729fea7bc87 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -2374,7 +2374,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont match_type(cx, ty, &paths::BTREEMAP) || is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) { if method.ident.name == sym!(len) { - let span = shorten_span(expr, sym!(collect)); + let span = shorten_needless_collect_span(expr); span_lint_and_sugg( cx, NEEDLESS_COLLECT, @@ -2386,20 +2386,20 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont ); } if method.ident.name == sym!(is_empty) { - let span = shorten_span(expr, sym!(iter)); + let span = shorten_needless_collect_span(expr); span_lint_and_sugg( cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, "replace with", - "get(0).is_none()".to_string(), + "next().is_none()".to_string(), Applicability::MachineApplicable, ); } if method.ident.name == sym!(contains) { let contains_arg = snippet(cx, args[1].span, "??"); - let span = shorten_span(expr, sym!(collect)); + let span = shorten_needless_collect_span(expr); span_lint_and_then( cx, NEEDLESS_COLLECT, @@ -2579,13 +2579,13 @@ fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) } } -fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span { - let mut current_expr = expr; - while let ExprKind::MethodCall(ref path, ref span, ref args, _) = current_expr.kind { - if path.ident.name == target_fn_name { +fn shorten_needless_collect_span(expr: &Expr<'_>) -> Span { + if_chain! { + if let ExprKind::MethodCall(.., args, _) = &expr.kind; + if let ExprKind::MethodCall(_, span, ..) = &args[0].kind; + then { return expr.span.with_lo(span.lo()); } - current_expr = &args[0]; } - unreachable!() + unreachable!(); } diff --git a/tests/ui/crashes/ice-5872.rs b/tests/ui/crashes/ice-5872.rs new file mode 100644 index 000000000000..68afa8f8c3a8 --- /dev/null +++ b/tests/ui/crashes/ice-5872.rs @@ -0,0 +1,5 @@ +#![warn(clippy::needless_collect)] + +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::>().is_empty(); +} diff --git a/tests/ui/crashes/ice-5872.stderr b/tests/ui/crashes/ice-5872.stderr new file mode 100644 index 000000000000..a60ca345cf78 --- /dev/null +++ b/tests/ui/crashes/ice-5872.stderr @@ -0,0 +1,10 @@ +error: avoid using `collect()` when not needed + --> $DIR/ice-5872.rs:4:39 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>().is_empty(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` + | + = note: `-D clippy::needless-collect` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index be37dc16b9a3..7f2fcf02f6b5 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -5,11 +5,11 @@ use std::collections::{BTreeSet, HashMap, HashSet}; #[warn(clippy::needless_collect)] -#[allow(unused_variables, clippy::iter_cloned_collect)] +#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)] fn main() { let sample = [1; 5]; let len = sample.iter().count(); - if sample.get(0).is_none() { + if sample.iter().next().is_none() { // Empty } sample.iter().cloned().any(|x| x == 1); diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 7ee603afeb07..788a9eb3264e 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -5,7 +5,7 @@ use std::collections::{BTreeSet, HashMap, HashSet}; #[warn(clippy::needless_collect)] -#[allow(unused_variables, clippy::iter_cloned_collect)] +#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)] fn main() { let sample = [1; 5]; let len = sample.iter().collect::>().len(); diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 9113aad90dd7..2a9539d59759 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -7,10 +7,10 @@ LL | let len = sample.iter().collect::>().len(); = note: `-D clippy::needless-collect` implied by `-D warnings` error: avoid using `collect()` when not needed - --> $DIR/needless_collect.rs:12:15 + --> $DIR/needless_collect.rs:12:22 | LL | if sample.iter().collect::>().is_empty() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get(0).is_none()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed --> $DIR/needless_collect.rs:15:28