Merge for_loop_over_option and for_loop_over_result lints into for_loop_over_fallible lint

This commit is contained in:
ThibsG 2020-05-03 15:16:00 +02:00 committed by Thibaud Genty
parent 0e8be599cd
commit adbdf7549c
6 changed files with 52 additions and 76 deletions

View file

@ -1361,8 +1361,7 @@ Released 2018-09-13
[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation
[`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map [`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map
[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option [`for_loop_over_fallible`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_fallible
[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result
[`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy
[`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref
[`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send

View file

@ -615,8 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&loops::EXPLICIT_INTO_ITER_LOOP, &loops::EXPLICIT_INTO_ITER_LOOP,
&loops::EXPLICIT_ITER_LOOP, &loops::EXPLICIT_ITER_LOOP,
&loops::FOR_KV_MAP, &loops::FOR_KV_MAP,
&loops::FOR_LOOP_OVER_OPTION, &loops::FOR_LOOP_OVER_FALLIBLE,
&loops::FOR_LOOP_OVER_RESULT,
&loops::ITER_NEXT_LOOP, &loops::ITER_NEXT_LOOP,
&loops::MANUAL_MEMCPY, &loops::MANUAL_MEMCPY,
&loops::MUT_RANGE_BOUND, &loops::MUT_RANGE_BOUND,
@ -1265,8 +1264,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::EMPTY_LOOP),
LintId::of(&loops::EXPLICIT_COUNTER_LOOP), LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
LintId::of(&loops::FOR_KV_MAP), LintId::of(&loops::FOR_KV_MAP),
LintId::of(&loops::FOR_LOOP_OVER_OPTION), LintId::of(&loops::FOR_LOOP_OVER_FALLIBLE),
LintId::of(&loops::FOR_LOOP_OVER_RESULT),
LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::ITER_NEXT_LOOP),
LintId::of(&loops::MANUAL_MEMCPY), LintId::of(&loops::MANUAL_MEMCPY),
LintId::of(&loops::MUT_RANGE_BOUND), LintId::of(&loops::MUT_RANGE_BOUND),
@ -1641,8 +1639,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES), LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
LintId::of(&loops::FOR_LOOP_OVER_OPTION), LintId::of(&loops::FOR_LOOP_OVER_FALLIBLE),
LintId::of(&loops::FOR_LOOP_OVER_RESULT),
LintId::of(&loops::ITER_NEXT_LOOP), LintId::of(&loops::ITER_NEXT_LOOP),
LintId::of(&loops::NEVER_LOOP), LintId::of(&loops::NEVER_LOOP),
LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION),

View file

@ -168,7 +168,7 @@ declare_clippy_lint! {
} }
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for `for` loops over `Option` values. /// **What it does:** Checks for `for` loops over `Option` or `Result` values.
/// ///
/// **Why is this bad?** Readability. This is more clearly expressed as an `if /// **Why is this bad?** Readability. This is more clearly expressed as an `if
/// let`. /// let`.
@ -176,47 +176,38 @@ declare_clippy_lint! {
/// **Known problems:** None. /// **Known problems:** None.
/// ///
/// **Example:** /// **Example:**
/// ```ignore /// ```rust
/// for x in option { /// # let opt = Some(1);
/// .. ///
/// // Bad
/// for x in opt {
/// // ..
/// }
///
/// // Good
/// if let Some(x) = opt {
/// // ..
/// } /// }
/// ``` /// ```
/// ///
/// This should be /// // or
/// ```ignore ///
/// if let Some(x) = option { /// ```rust
/// .. /// # let res: Result<i32, std::io::Error> = Ok(1);
///
/// // Bad
/// for x in &res {
/// // ..
/// }
///
/// // Good
/// if let Ok(x) = res {
/// // ..
/// } /// }
/// ``` /// ```
pub FOR_LOOP_OVER_OPTION, pub FOR_LOOP_OVER_FALLIBLE,
correctness, correctness,
"for-looping over an `Option`, which is more clearly expressed as an `if let`" "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"
}
declare_clippy_lint! {
/// **What it does:** Checks for `for` loops over `Result` values.
///
/// **Why is this bad?** Readability. This is more clearly expressed as an `if
/// let`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```ignore
/// for x in result {
/// ..
/// }
/// ```
///
/// This should be
/// ```ignore
/// if let Ok(x) = result {
/// ..
/// }
/// ```
pub FOR_LOOP_OVER_RESULT,
correctness,
"for-looping over a `Result`, which is more clearly expressed as an `if let`"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -435,8 +426,7 @@ declare_lint_pass!(Loops => [
EXPLICIT_ITER_LOOP, EXPLICIT_ITER_LOOP,
EXPLICIT_INTO_ITER_LOOP, EXPLICIT_INTO_ITER_LOOP,
ITER_NEXT_LOOP, ITER_NEXT_LOOP,
FOR_LOOP_OVER_RESULT, FOR_LOOP_OVER_FALLIBLE,
FOR_LOOP_OVER_OPTION,
WHILE_LET_LOOP, WHILE_LET_LOOP,
NEEDLESS_COLLECT, NEEDLESS_COLLECT,
EXPLICIT_COUNTER_LOOP, EXPLICIT_COUNTER_LOOP,
@ -1283,7 +1273,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e
ITER_NEXT_LOOP, ITER_NEXT_LOOP,
expr.span, expr.span,
"you are iterating over `Iterator::next()` which is an Option; this will compile but is \ "you are iterating over `Iterator::next()` which is an Option; this will compile but is \
probably not what you want", probably not what you want",
); );
next_loop_linted = true; next_loop_linted = true;
} }
@ -1300,11 +1290,11 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
if is_type_diagnostic_item(cx, ty, sym!(option_type)) { if is_type_diagnostic_item(cx, ty, sym!(option_type)) {
span_lint_and_help( span_lint_and_help(
cx, cx,
FOR_LOOP_OVER_OPTION, FOR_LOOP_OVER_FALLIBLE,
arg.span, arg.span,
&format!( &format!(
"for loop over `{0}`, which is an `Option`. This is more readably written as an \ "for loop over `{0}`, which is an `Option`. This is more readably written as an \
`if let` statement.", `if let` statement.",
snippet(cx, arg.span, "_") snippet(cx, arg.span, "_")
), ),
None, None,
@ -1317,11 +1307,11 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
} else if is_type_diagnostic_item(cx, ty, sym!(result_type)) { } else if is_type_diagnostic_item(cx, ty, sym!(result_type)) {
span_lint_and_help( span_lint_and_help(
cx, cx,
FOR_LOOP_OVER_RESULT, FOR_LOOP_OVER_FALLIBLE,
arg.span, arg.span,
&format!( &format!(
"for loop over `{0}`, which is a `Result`. This is more readably written as an \ "for loop over `{0}`, which is a `Result`. This is more readably written as an \
`if let` statement.", `if let` statement.",
snippet(cx, arg.span, "_") snippet(cx, arg.span, "_")
), ),
None, None,

View file

@ -676,16 +676,9 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
module: "loops", module: "loops",
}, },
Lint { Lint {
name: "for_loop_over_option", name: "for_loop_over_fallible",
group: "correctness", group: "correctness",
desc: "for-looping over an `Option`, which is more clearly expressed as an `if let`", desc: "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`",
deprecation: None,
module: "loops",
},
Lint {
name: "for_loop_over_result",
group: "correctness",
desc: "for-looping over a `Result`, which is more clearly expressed as an `if let`",
deprecation: None, deprecation: None,
module: "loops", module: "loops",
}, },

View file

@ -1,18 +1,16 @@
#![warn(clippy::for_loop_over_option, clippy::for_loop_over_result)] #![warn(clippy::for_loop_over_fallible)]
/// Tests for_loop_over_result and for_loop_over_option fn for_loop_over_fallible() {
fn for_loop_over_option_and_result() {
let option = Some(1); let option = Some(1);
let result = option.ok_or("x not found"); let result = option.ok_or("x not found");
let v = vec![0, 1, 2]; let v = vec![0, 1, 2];
// check FOR_LOOP_OVER_OPTION lint // check over an `Option`
for x in option { for x in option {
println!("{}", x); println!("{}", x);
} }
// check FOR_LOOP_OVER_RESULT lint // check over a `Result`
for x in result { for x in result {
println!("{}", x); println!("{}", x);
} }

View file

@ -1,23 +1,22 @@
error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement.
--> $DIR/for_loop_over_option_result.rs:11:14 --> $DIR/for_loop_over_fallible.rs:9:14
| |
LL | for x in option { LL | for x in option {
| ^^^^^^ | ^^^^^^
| |
= note: `-D clippy::for-loop-over-option` implied by `-D warnings` = note: `-D clippy::for-loop-over-fallible` implied by `-D warnings`
= help: consider replacing `for x in option` with `if let Some(x) = option` = help: consider replacing `for x in option` with `if let Some(x) = option`
error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement. error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement.
--> $DIR/for_loop_over_option_result.rs:16:14 --> $DIR/for_loop_over_fallible.rs:14:14
| |
LL | for x in result { LL | for x in result {
| ^^^^^^ | ^^^^^^
| |
= note: `-D clippy::for-loop-over-result` implied by `-D warnings`
= help: consider replacing `for x in result` with `if let Ok(x) = result` = help: consider replacing `for x in result` with `if let Ok(x) = result`
error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement.
--> $DIR/for_loop_over_option_result.rs:20:14 --> $DIR/for_loop_over_fallible.rs:18:14
| |
LL | for x in option.ok_or("x not found") { LL | for x in option.ok_or("x not found") {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -25,7 +24,7 @@ LL | for x in option.ok_or("x not found") {
= help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")` = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")`
error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
--> $DIR/for_loop_over_option_result.rs:26:14 --> $DIR/for_loop_over_fallible.rs:24:14
| |
LL | for x in v.iter().next() { LL | for x in v.iter().next() {
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
@ -33,7 +32,7 @@ LL | for x in v.iter().next() {
= note: `#[deny(clippy::iter_next_loop)]` on by default = note: `#[deny(clippy::iter_next_loop)]` on by default
error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement.
--> $DIR/for_loop_over_option_result.rs:31:14 --> $DIR/for_loop_over_fallible.rs:29:14
| |
LL | for x in v.iter().next().and(Some(0)) { LL | for x in v.iter().next().and(Some(0)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -41,7 +40,7 @@ LL | for x in v.iter().next().and(Some(0)) {
= help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))` = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))`
error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement. error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement.
--> $DIR/for_loop_over_option_result.rs:35:14 --> $DIR/for_loop_over_fallible.rs:33:14
| |
LL | for x in v.iter().next().ok_or("x not found") { LL | for x in v.iter().next().ok_or("x not found") {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -49,7 +48,7 @@ LL | for x in v.iter().next().ok_or("x not found") {
= help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")` = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")`
error: this loop never actually loops error: this loop never actually loops
--> $DIR/for_loop_over_option_result.rs:47:5 --> $DIR/for_loop_over_fallible.rs:45:5
| |
LL | / while let Some(x) = option { LL | / while let Some(x) = option {
LL | | println!("{}", x); LL | | println!("{}", x);
@ -60,7 +59,7 @@ LL | | }
= note: `#[deny(clippy::never_loop)]` on by default = note: `#[deny(clippy::never_loop)]` on by default
error: this loop never actually loops error: this loop never actually loops
--> $DIR/for_loop_over_option_result.rs:53:5 --> $DIR/for_loop_over_fallible.rs:51:5
| |
LL | / while let Ok(x) = result { LL | / while let Ok(x) = result {
LL | | println!("{}", x); LL | | println!("{}", x);