From 0f2b1193f9501ffd06f9bf2ea8ab85a4db92f47b Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Mon, 11 May 2020 00:53:31 +0200 Subject: [PATCH] Remove reverse_range_loop lint --- CHANGELOG.md | 1 - clippy_lints/src/lib.rs | 7 +- clippy_lints/src/loops.rs | 102 +---------------------------- src/lintlist/mod.rs | 6 +- tests/ui/for_loop_fixable.fixed | 54 --------------- tests/ui/for_loop_fixable.rs | 54 --------------- tests/ui/for_loop_fixable.stderr | 88 +++++-------------------- tests/ui/for_loop_unfixable.rs | 18 ----- tests/ui/for_loop_unfixable.stderr | 11 ++-- tests/ui/manual_memcpy.rs | 2 +- 10 files changed, 32 insertions(+), 311 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33b277fbd31..b25ef049356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1545,7 +1545,6 @@ Released 2018-09-13 [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used -[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1cb10a4651..0c4daeb731f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -624,7 +624,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::NEEDLESS_COLLECT, &loops::NEEDLESS_RANGE_LOOP, &loops::NEVER_LOOP, - &loops::REVERSE_RANGE_LOOP, &loops::WHILE_IMMUTABLE_CONDITION, &loops::WHILE_LET_LOOP, &loops::WHILE_LET_ON_ITERATOR, @@ -1284,7 +1283,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_COLLECT), LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::NEVER_LOOP), - LintId::of(&loops::REVERSE_RANGE_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), @@ -1658,7 +1656,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::FOR_LOOP_OVER_RESULT), LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::NEVER_LOOP), - LintId::of(&loops::REVERSE_RANGE_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), @@ -1788,6 +1785,10 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) { "unsafe_vector_initialization", "the replacement suggested by this lint had substantially different behavior", ); + store.register_removed( + "reverse_range_loop", + "this lint is now included in reversed_empty_ranges", + ); } /// Register renamed lints. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2bbf4dba614..0bc6b70855b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use crate::consts::constant; use crate::reexport::Name; use crate::utils::paths; use crate::utils::usage::{is_unused, mutated_variables}; @@ -8,7 +8,7 @@ use crate::utils::{ multispan_sugg, snippet, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, SpanlessEq, }; -use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg}; +use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sugg}; use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -270,30 +270,6 @@ declare_clippy_lint! { "collecting an iterator when collect is not needed" } -declare_clippy_lint! { - /// **What it does:** Checks for loops over ranges `x..y` where both `x` and `y` - /// are constant and `x` is greater or equal to `y`, unless the range is - /// reversed or has a negative `.step_by(_)`. - /// - /// **Why is it bad?** Such loops will either be skipped or loop until - /// wrap-around (in debug code, this may `panic!()`). Both options are probably - /// not intended. - /// - /// **Known problems:** The lint cannot catch loops over dynamically defined - /// ranges. Doing this would require simulating all possible inputs and code - /// paths through the program, which would be complex and error-prone. - /// - /// **Example:** - /// ```ignore - /// for x in 5..10 - 5 { - /// .. - /// } // oops, stray `-` - /// ``` - pub REVERSE_RANGE_LOOP, - correctness, - "iteration over an empty range, such as `10..0` or `5..5`" -} - declare_clippy_lint! { /// **What it does:** Checks `for` loops over slices with an explicit counter /// and suggests the use of `.enumerate()`. @@ -463,7 +439,6 @@ declare_lint_pass!(Loops => [ FOR_LOOP_OVER_OPTION, WHILE_LET_LOOP, NEEDLESS_COLLECT, - REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP, EMPTY_LOOP, WHILE_LET_ON_ITERATOR, @@ -761,7 +736,6 @@ fn check_for_loop<'a, 'tcx>( expr: &'tcx Expr<'_>, ) { check_for_loop_range(cx, pat, arg, body, expr); - check_for_loop_reverse_range(cx, arg, expr); check_for_loop_arg(cx, pat, arg, expr); check_for_loop_explicit_counter(cx, pat, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); @@ -1248,78 +1222,6 @@ fn is_end_eq_array_len<'tcx>( false } -fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { - // if this for loop is iterating over a two-sided range... - if let Some(higher::Range { - start: Some(start), - end: Some(end), - limits, - }) = higher::range(cx, arg) - { - // ...and both sides are compile-time constant integers... - if let Some((start_idx, _)) = constant(cx, cx.tables, start) { - if let Some((end_idx, _)) = constant(cx, cx.tables, end) { - // ...and the start index is greater than the end index, - // this loop will never run. This is often confusing for developers - // who think that this will iterate from the larger value to the - // smaller value. - let ty = cx.tables.expr_ty(start); - let (sup, eq) = match (start_idx, end_idx) { - (Constant::Int(start_idx), Constant::Int(end_idx)) => ( - match ty.kind { - ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity), - ty::Uint(_) => start_idx > end_idx, - _ => false, - }, - start_idx == end_idx, - ), - _ => (false, false), - }; - - if sup { - let start_snippet = snippet(cx, start.span, "_"); - let end_snippet = snippet(cx, end.span, "_"); - let dots = if limits == ast::RangeLimits::Closed { - "..=" - } else { - ".." - }; - - span_lint_and_then( - cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - |diag| { - diag.span_suggestion( - arg.span, - "consider using the following if you are attempting to iterate over this \ - range in reverse", - format!( - "({end}{dots}{start}).rev()", - end = end_snippet, - dots = dots, - start = start_snippet - ), - Applicability::MaybeIncorrect, - ); - }, - ); - } else if eq && limits != ast::RangeLimits::Closed { - // if they are equal, it's also problematic - this loop - // will never run. - span_lint( - cx, - REVERSE_RANGE_LOOP, - expr.span, - "this range is empty so this for loop will never run", - ); - } - } - } - } -} - fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) { let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 51d1cb2216a..e1a6d4bdd31 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1922,11 +1922,11 @@ pub static ref ALL_LINTS: Vec = vec![ module: "methods", }, Lint { - name: "reverse_range_loop", + name: "reversed_empty_ranges", group: "correctness", - desc: "iteration over an empty range, such as `10..0` or `5..5`", + desc: "reversing the limits of range expressions, resulting in empty ranges", deprecation: None, - module: "loops", + module: "ranges", }, Lint { name: "same_functions_in_if_condition", diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index 5fc84ada9ef..249a88a0b39 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -21,7 +21,6 @@ impl Unrelated { clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, - clippy::reverse_range_loop, clippy::for_kv_map )] #[allow( @@ -32,61 +31,8 @@ impl Unrelated { )] #[allow(clippy::many_single_char_names, unused_variables)] fn main() { - const MAX_LEN: usize = 42; let mut vec = vec![1, 2, 3, 4]; - for i in (0..10).rev() { - println!("{}", i); - } - - for i in (0..=10).rev() { - println!("{}", i); - } - - for i in (0..MAX_LEN).rev() { - println!("{}", i); - } - - for i in 5..=5 { - // not an error, this is the range with only one element “5” - println!("{}", i); - } - - for i in 0..10 { - // not an error, the start index is less than the end index - println!("{}", i); - } - - for i in -10..0 { - // not an error - println!("{}", i); - } - - for i in (10..0).map(|x| x * 2) { - // not an error, it can't be known what arbitrary methods do to a range - println!("{}", i); - } - - // testing that the empty range lint folds constants - for i in (5 + 4..10).rev() { - println!("{}", i); - } - - for i in ((3 - 1)..(5 + 2)).rev() { - println!("{}", i); - } - - for i in (2 * 2)..(2 * 3) { - // no error, 4..6 is fine - println!("{}", i); - } - - let x = 42; - for i in x..10 { - // no error, not constant-foldable - println!("{}", i); - } - // See #601 for i in 0..10 { // no error, id_col does not exist outside the loop diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 4165b0dc004..306d85a6351 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -21,7 +21,6 @@ impl Unrelated { clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, - clippy::reverse_range_loop, clippy::for_kv_map )] #[allow( @@ -32,61 +31,8 @@ impl Unrelated { )] #[allow(clippy::many_single_char_names, unused_variables)] fn main() { - const MAX_LEN: usize = 42; let mut vec = vec![1, 2, 3, 4]; - for i in 10..0 { - println!("{}", i); - } - - for i in 10..=0 { - println!("{}", i); - } - - for i in MAX_LEN..0 { - println!("{}", i); - } - - for i in 5..=5 { - // not an error, this is the range with only one element “5” - println!("{}", i); - } - - for i in 0..10 { - // not an error, the start index is less than the end index - println!("{}", i); - } - - for i in -10..0 { - // not an error - println!("{}", i); - } - - for i in (10..0).map(|x| x * 2) { - // not an error, it can't be known what arbitrary methods do to a range - println!("{}", i); - } - - // testing that the empty range lint folds constants - for i in 10..5 + 4 { - println!("{}", i); - } - - for i in (5 + 2)..(3 - 1) { - println!("{}", i); - } - - for i in (2 * 2)..(2 * 3) { - // no error, 4..6 is fine - println!("{}", i); - } - - let x = 42; - for i in x..10 { - // no error, not constant-foldable - println!("{}", i); - } - // See #601 for i in 0..10 { // no error, id_col does not exist outside the loop diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr index cffb4b9f0a9..ddfe66d675f 100644 --- a/tests/ui/for_loop_fixable.stderr +++ b/tests/ui/for_loop_fixable.stderr @@ -1,61 +1,5 @@ -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:38:14 - | -LL | for i in 10..0 { - | ^^^^^ - | - = note: `-D clippy::reverse-range-loop` implied by `-D warnings` -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (0..10).rev() { - | ^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:42:14 - | -LL | for i in 10..=0 { - | ^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (0..=10).rev() { - | ^^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:46:14 - | -LL | for i in MAX_LEN..0 { - | ^^^^^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (0..MAX_LEN).rev() { - | ^^^^^^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:71:14 - | -LL | for i in 10..5 + 4 { - | ^^^^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in (5 + 4..10).rev() { - | ^^^^^^^^^^^^^^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:75:14 - | -LL | for i in (5 + 2)..(3 - 1) { - | ^^^^^^^^^^^^^^^^ - | -help: consider using the following if you are attempting to iterate over this range in reverse - | -LL | for i in ((3 - 1)..(5 + 2)).rev() { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:97:15 + --> $DIR/for_loop_fixable.rs:43:15 | LL | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -63,13 +7,13 @@ LL | for _v in vec.iter() {} = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:99:15 + --> $DIR/for_loop_fixable.rs:45:15 | LL | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:102:15 + --> $DIR/for_loop_fixable.rs:48:15 | LL | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` @@ -77,76 +21,76 @@ LL | for _v in out_vec.into_iter() {} = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:107:15 + --> $DIR/for_loop_fixable.rs:53:15 | LL | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:111:15 + --> $DIR/for_loop_fixable.rs:57:15 | LL | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:116:15 + --> $DIR/for_loop_fixable.rs:62:15 | LL | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:119:15 + --> $DIR/for_loop_fixable.rs:65:15 | LL | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:122:15 + --> $DIR/for_loop_fixable.rs:68:15 | LL | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:125:15 + --> $DIR/for_loop_fixable.rs:71:15 | LL | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:128:15 + --> $DIR/for_loop_fixable.rs:74:15 | LL | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:131:15 + --> $DIR/for_loop_fixable.rs:77:15 | LL | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:134:15 + --> $DIR/for_loop_fixable.rs:80:15 | LL | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:309:18 + --> $DIR/for_loop_fixable.rs:255:18 | LL | for i in iterator.into_iter() { | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:329:18 + --> $DIR/for_loop_fixable.rs:275:18 | LL | for _ in t.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:331:18 + --> $DIR/for_loop_fixable.rs:277:18 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` -error: aborting due to 20 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs index 179b255e08c..e73536052f0 100644 --- a/tests/ui/for_loop_unfixable.rs +++ b/tests/ui/for_loop_unfixable.rs @@ -5,7 +5,6 @@ clippy::explicit_iter_loop, clippy::explicit_into_iter_loop, clippy::iter_next_loop, - clippy::reverse_range_loop, clippy::for_kv_map )] #[allow( @@ -16,25 +15,8 @@ unused, dead_code )] -#[allow(clippy::many_single_char_names, unused_variables)] fn main() { - for i in 5..5 { - println!("{}", i); - } - let vec = vec![1, 2, 3, 4]; for _v in vec.iter().next() {} - - for i in (5 + 2)..(8 - 1) { - println!("{}", i); - } - - const ZERO: usize = 0; - - for i in ZERO..vec.len() { - if f(&vec[i], &vec[i]) { - panic!("at the disco"); - } - } } diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr index 1da8e0f3588..1c9287b6acb 100644 --- a/tests/ui/for_loop_unfixable.stderr +++ b/tests/ui/for_loop_unfixable.stderr @@ -1,9 +1,10 @@ -error[E0425]: cannot find function `f` in this scope - --> $DIR/for_loop_unfixable.rs:36:12 +error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want + --> $DIR/for_loop_unfixable.rs:21:15 | -LL | if f(&vec[i], &vec[i]) { - | ^ help: a local variable with a similar name exists: `i` +LL | for _v in vec.iter().next() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-next-loop` implied by `-D warnings` error: aborting due to previous error -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/manual_memcpy.rs b/tests/ui/manual_memcpy.rs index 9c24d6d4db1..0083f94798f 100644 --- a/tests/ui/manual_memcpy.rs +++ b/tests/ui/manual_memcpy.rs @@ -104,7 +104,7 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { dst[i - 0] = src[i]; } - #[allow(clippy::reverse_range_loop)] + #[allow(clippy::reversed_empty_ranges)] for i in 0..0 { dst[i] = src[i]; }