1 use clippy_utils
::diagnostics
::span_lint_and_sugg
;
2 use clippy_utils
::higher
;
3 use clippy_utils
::method_chain_args
;
4 use clippy_utils
::source
::snippet_with_applicability
;
5 use clippy_utils
::ty
::is_type_diagnostic_item
;
6 use if_chain
::if_chain
;
7 use rustc_errors
::Applicability
;
8 use rustc_hir
::{Expr, ExprKind, PatKind, QPath}
;
9 use rustc_lint
::{LateContext, LateLintPass}
;
10 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
13 declare_clippy_lint
! {
15 /// Checks for unnecessary `ok()` in `while let`.
17 /// ### Why is this bad?
18 /// Calling `ok()` in `while let` is unnecessary, instead match
23 /// while let Some(value) = iter.next().ok() {
27 /// if let Some(valie) = iter.next().ok() {
33 /// while let Ok(value) = iter.next() {
37 /// if let Ok(value) = iter.next() {
43 "usage of `ok()` in `let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
46 declare_lint_pass
!(MatchResultOk
=> [MATCH_RESULT_OK
]);
48 impl<'tcx
> LateLintPass
<'tcx
> for MatchResultOk
{
49 fn check_expr(&mut self, cx
: &LateContext
<'tcx
>, expr
: &'tcx Expr
<'_
>) {
50 let (let_pat
, let_expr
, ifwhile
) =
51 if let Some(higher
::IfLet { let_pat, let_expr, .. }
) = higher
::IfLet
::hir(cx
, expr
) {
52 (let_pat
, let_expr
, "if")
53 } else if let Some(higher
::WhileLet { let_pat, let_expr, .. }
) = higher
::WhileLet
::hir(expr
) {
54 (let_pat
, let_expr
, "while")
60 if let ExprKind
::MethodCall(_
, ok_span
, [ref result_types_0
, ..], _
) = let_expr
.kind
; //check is expr.ok() has type Result<T,E>.ok(, _)
61 if let PatKind
::TupleStruct(QPath
::Resolved(_
, x
), y
, _
) = let_pat
.kind
; //get operation
62 if method_chain_args(let_expr
, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
63 if is_type_diagnostic_item(cx
, cx
.typeck_results().expr_ty(result_types_0
), sym
::Result
);
64 if rustc_hir_pretty
::to_string(rustc_hir_pretty
::NO_ANN
, |s
| s
.print_path(x
, false)) == "Some";
68 let mut applicability
= Applicability
::MachineApplicable
;
69 let some_expr_string
= snippet_with_applicability(cx
, y
[0].span
, "", &mut applicability
);
70 let trimmed_ok
= snippet_with_applicability(cx
, let_expr
.span
.until(ok_span
), "", &mut applicability
);
75 trimmed_ok
.trim().trim_end_matches('
.'
),
80 expr
.span
.with_hi(let_expr
.span
.hi()),
81 "matching on `Some` with `ok()` is redundant",
82 &format
!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string
),