Skip to content

Commit fc86396

Browse files
committed
Adding new linting
1 parent 5e1e9b0 commit fc86396

File tree

6 files changed

+164
-0
lines changed

6 files changed

+164
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,7 @@ Released 2018-09-13
30263026
[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
30273027
[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
30283028
[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
3029+
[`while_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_some_result
30293030
[`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies
30303031
[`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm
30313032
[`wildcard_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports

clippy_lints/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ mod vec;
376376
mod vec_init_then_push;
377377
mod vec_resize_to_zero;
378378
mod verbose_file_reads;
379+
mod while_let_some_result;
379380
mod wildcard_dependencies;
380381
mod wildcard_imports;
381382
mod write;
@@ -988,6 +989,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
988989
vec_init_then_push::VEC_INIT_THEN_PUSH,
989990
vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
990991
verbose_file_reads::VERBOSE_FILE_READS,
992+
while_let_some_result::WHILE_LET_SOME_RESULT,
991993
wildcard_dependencies::WILDCARD_DEPENDENCIES,
992994
wildcard_imports::ENUM_GLOB_USE,
993995
wildcard_imports::WILDCARD_IMPORTS,
@@ -1468,6 +1470,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
14681470
LintId::of(vec::USELESS_VEC),
14691471
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
14701472
LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
1473+
LintId::of(while_let_some_result::WHILE_LET_SOME_RESULT),
14711474
LintId::of(write::PRINTLN_EMPTY_STRING),
14721475
LintId::of(write::PRINT_LITERAL),
14731476
LintId::of(write::PRINT_WITH_NEWLINE),
@@ -1580,6 +1583,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15801583
LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
15811584
LintId::of(unused_unit::UNUSED_UNIT),
15821585
LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
1586+
LintId::of(while_let_some_result::WHILE_LET_SOME_RESULT),
15831587
LintId::of(write::PRINTLN_EMPTY_STRING),
15841588
LintId::of(write::PRINT_LITERAL),
15851589
LintId::of(write::PRINT_WITH_NEWLINE),
@@ -1972,6 +1976,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
19721976
store.register_late_pass(|| box missing_inline::MissingInline);
19731977
store.register_late_pass(move || box exhaustive_items::ExhaustiveItems);
19741978
store.register_late_pass(|| box if_let_some_result::OkIfLet);
1979+
store.register_late_pass(|| box while_let_some_result::WhileLetSomeResult);
19751980
store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl);
19761981
store.register_late_pass(|| box unused_io_amount::UnusedIoAmount);
19771982
let enum_variant_size_threshold = conf.enum_variant_size_threshold;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::method_chain_args;
3+
use clippy_utils::source::snippet_with_applicability;
4+
use clippy_utils::ty::is_type_diagnostic_item;
5+
use if_chain::if_chain;
6+
use rustc_errors::Applicability;
7+
use rustc_hir::{Expr, ExprKind, MatchSource, PatKind, QPath};
8+
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_session::{declare_lint_pass, declare_tool_lint};
10+
use rustc_span::sym;
11+
12+
declare_clippy_lint! {
13+
/// ### What it does
14+
/// Checks for unnecessary `ok()` in `while let`.
15+
///
16+
/// ### Why is this bad?
17+
/// Calling `ok()` in `while let` is unnecessary, instead match
18+
/// on `Ok(pat)`
19+
///
20+
/// ### Example
21+
/// ```ignore
22+
/// while let Some(value) = iter.next().ok() {
23+
/// vec.push(value)
24+
/// }
25+
/// ```
26+
/// Use instead:
27+
/// ```ignore
28+
/// while let Ok(value) = iter.next() {
29+
/// vec.push(value)
30+
/// }
31+
/// ```
32+
pub WHILE_LET_SOME_RESULT,
33+
style,
34+
"usage of `ok()` in `while let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
35+
}
36+
37+
declare_lint_pass!(WhileLetSomeResult => [WHILE_LET_SOME_RESULT]);
38+
39+
impl<'tcx> LateLintPass<'tcx> for WhileLetSomeResult {
40+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
41+
if_chain! { //begin checking variables
42+
if let ExprKind::Match(op, body, MatchSource::WhileLetDesugar { .. }) = expr.kind; //test if expr is `while let`
43+
if let ExprKind::MethodCall(_, ok_span, result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
44+
if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _) = body[0].pat.kind; //get operation
45+
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
46+
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&result_types[0]), sym::result_type);
47+
if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";
48+
49+
then {
50+
let mut applicability = Applicability::MachineApplicable;
51+
let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
52+
let trimmed_ok = snippet_with_applicability(cx, op.span.until(ok_span), "", &mut applicability);
53+
let sugg = format!(
54+
"while let Ok({}) = {}",
55+
some_expr_string,
56+
trimmed_ok.trim().trim_end_matches('.'),
57+
);
58+
span_lint_and_sugg(
59+
cx,
60+
WHILE_LET_SOME_RESULT,
61+
expr.span.with_hi(op.span.hi()),
62+
"matching on `Some` with `ok()` is redundant",
63+
&format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string),
64+
sugg,
65+
applicability,
66+
);
67+
}
68+
}
69+
}
70+
}

tests/ui/while_let_some_result.fixed

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::while_let_some_result)]
4+
5+
struct Wat {
6+
counter: i32,
7+
}
8+
9+
impl Wat {
10+
fn next(&mut self) -> Result<i32, &str> {
11+
self.counter += 1;
12+
if self.counter < 5 {
13+
Ok(self.counter)
14+
} else {
15+
Err("Oh no")
16+
}
17+
}
18+
}
19+
20+
fn base_1(x: i32) {
21+
let mut wat = Wat { counter: x };
22+
while let Ok(a) = wat.next() {
23+
println!("{}", a);
24+
}
25+
}
26+
27+
fn base_2(x: i32) {
28+
let mut wat = Wat { counter: x };
29+
while let Ok(a) = wat.next() {
30+
println!("{}", a);
31+
}
32+
}
33+
34+
fn main() {
35+
let _ = base_1(1);
36+
let _ = base_2(2);
37+
}

tests/ui/while_let_some_result.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::while_let_some_result)]
4+
5+
struct Wat {
6+
counter: i32,
7+
}
8+
9+
impl Wat {
10+
fn next(&mut self) -> Result<i32, &str> {
11+
self.counter += 1;
12+
if self.counter < 5 {
13+
Ok(self.counter)
14+
} else {
15+
Err("Oh no")
16+
}
17+
}
18+
}
19+
20+
fn base_1(x: i32) {
21+
let mut wat = Wat { counter: x };
22+
while let Some(a) = wat.next().ok() {
23+
println!("{}", a);
24+
}
25+
}
26+
27+
fn base_2(x: i32) {
28+
let mut wat = Wat { counter: x };
29+
while let Ok(a) = wat.next() {
30+
println!("{}", a);
31+
}
32+
}
33+
34+
fn main() {
35+
let _ = base_1(1);
36+
let _ = base_2(2);
37+
}

tests/ui/while_let_some_result.stderr

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: matching on `Some` with `ok()` is redundant
2+
--> $DIR/while_let_some_result.rs:22:5
3+
|
4+
LL | while let Some(a) = wat.next().ok() {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::while-let-some-result` implied by `-D warnings`
8+
help: consider matching on `Ok(a)` and removing the call to `ok` instead
9+
|
10+
LL | while let Ok(a) = wat.next() {
11+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)