Skip to content

Commit e851bc7

Browse files
authored
Merge pull request rust-lang#1257 from KitFreddura/master
If let some lint
2 parents 85e3779 + c8aa35e commit e851bc7

File tree

6 files changed

+88
-3
lines changed

6 files changed

+88
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ All notable changes to this project will be documented in this file.
250250
[`for_loop_over_option`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option
251251
[`for_loop_over_result`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result
252252
[`identity_op`]: https://github.com/Manishearth/rust-clippy/wiki#identity_op
253+
[`if_let_some_result`]: https://github.com/Manishearth/rust-clippy/wiki#if_let_some_result
253254
[`if_not_else`]: https://github.com/Manishearth/rust-clippy/wiki#if_not_else
254255
[`if_same_then_else`]: https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else
255256
[`ifs_same_cond`]: https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ You can check out this great service at [clippy.bashy.io](https://clippy.bashy.i
174174

175175
## Lints
176176

177-
There are 172 lints included in this crate:
177+
There are 173 lints included in this crate:
178178

179179
name | default | triggers on
180180
---------------------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------
@@ -231,6 +231,7 @@ name
231231
[for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let`
232232
[for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let`
233233
[identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1`
234+
[if_let_some_result](https://github.com/Manishearth/rust-clippy/wiki#if_let_some_result) | warn | usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead
234235
[if_not_else](https://github.com/Manishearth/rust-clippy/wiki#if_not_else) | allow | `if` branches that could be swapped so no negation operation is necessary on the condition
235236
[if_same_then_else](https://github.com/Manishearth/rust-clippy/wiki#if_same_then_else) | warn | if with the same *then* and *else* blocks
236237
[ifs_same_cond](https://github.com/Manishearth/rust-clippy/wiki#ifs_same_cond) | warn | consecutive `ifs` with the same condition

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ pub mod neg_multiply;
106106
pub mod new_without_default;
107107
pub mod no_effect;
108108
pub mod non_expressive_names;
109+
pub mod ok_if_let;
109110
pub mod open_options;
110111
pub mod overflow_check_conditional;
111112
pub mod panic;
@@ -254,6 +255,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
254255
reg.register_late_lint_pass(box let_if_seq::LetIfSeq);
255256
reg.register_late_lint_pass(box eval_order_dependence::EvalOrderDependence);
256257
reg.register_late_lint_pass(box missing_doc::MissingDoc::new());
258+
reg.register_late_lint_pass(box ok_if_let::OkIfLetPass);
257259

258260
reg.register_lint_group("clippy_restrictions", vec![
259261
arithmetic::FLOAT_ARITHMETIC,
@@ -404,6 +406,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
404406
no_effect::NO_EFFECT,
405407
no_effect::UNNECESSARY_OPERATION,
406408
non_expressive_names::MANY_SINGLE_CHAR_NAMES,
409+
ok_if_let::IF_LET_SOME_RESULT,
407410
open_options::NONSENSICAL_OPEN_OPTIONS,
408411
overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
409412
panic::PANIC_PARAMS,

clippy_lints/src/ok_if_let.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use rustc::lint::*;
2+
use rustc::hir::*;
3+
use utils::{paths, method_chain_args, span_help_and_lint, match_type, snippet};
4+
5+
/// **What it does:*** Checks for unnecessary `ok()` in if let.
6+
///
7+
/// **Why is this bad?** Calling `ok()` in if let is unnecessary, instead match on `Ok(pat)`
8+
///
9+
/// **Known problems:** None.
10+
///
11+
/// **Example:**
12+
/// ```rustc
13+
/// for result in iter {
14+
/// if let Some(bench) = try!(result).parse().ok() {
15+
/// vec.push(bench)
16+
/// }
17+
/// }
18+
/// ```
19+
declare_lint! {
20+
pub IF_LET_SOME_RESULT,
21+
Warn,
22+
"usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
23+
}
24+
25+
#[derive(Copy, Clone)]
26+
pub struct OkIfLetPass;
27+
28+
impl LintPass for OkIfLetPass {
29+
fn get_lints(&self) -> LintArray {
30+
lint_array!(IF_LET_SOME_RESULT)
31+
}
32+
}
33+
34+
impl LateLintPass for OkIfLetPass {
35+
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
36+
if_let_chain! {[ //begin checking variables
37+
let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
38+
let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
39+
let ExprMethodCall(_, _, ref result_types) = op.node, //check is expr.ok() has type Result<T,E>.ok()
40+
let PatKind::TupleStruct(ref x, ref y, _) = body[0].pats[0].node, //get operation
41+
let Some(_) = method_chain_args(op, &["ok"]) //test to see if using ok() methoduse std::marker::Sized;
42+
43+
], {
44+
let is_result_type = match_type(cx, cx.tcx.expr_ty(&result_types[0]), &paths::RESULT);
45+
let some_expr_string = snippet(cx, y[0].span, "");
46+
if print::path_to_string(x) == "Some" && is_result_type {
47+
span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,
48+
"Matching on `Some` with `ok()` is redundant",
49+
&format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string));
50+
}
51+
}}
52+
}
53+
}

clippy_lints/src/zero_div_zero.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ impl LateLintPass for Pass {
3838
// do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
3939
let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left),
4040
let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right),
41-
let Some(0.0) = lhs_value.parse().ok(),
42-
let Some(0.0) = rhs_value.parse().ok()
41+
let Ok(0.0) = lhs_value.parse(),
42+
let Ok(0.0) = rhs_value.parse()
4343
], {
4444
// since we're about to suggest a use of std::f32::NaN or std::f64::NaN,
4545
// match the precision of the literals that are given.

tests/compile-fail/ok_if_let.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(plugin)]
2+
#![plugin(clippy)]
3+
4+
#![deny(if_let_some_result)]
5+
6+
fn str_to_int(x: &str) -> i32 {
7+
if let Some(y) = x.parse().ok() {
8+
//~^ERROR Matching on `Some` with `ok()` is redundant
9+
y
10+
} else {
11+
0
12+
}
13+
}
14+
15+
fn str_to_int_ok(x: &str) -> i32 {
16+
if let Ok(y) = x.parse() {
17+
y
18+
} else {
19+
0
20+
}
21+
}
22+
23+
fn main() {
24+
let y = str_to_int("1");
25+
let z = str_to_int_ok("2");
26+
println!("{}{}", y, z);
27+
}

0 commit comments

Comments
 (0)