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(value) = iter.next().ok() {
33 /// while let Ok(value) = iter.next() {
37 /// if let Ok(value) = iter.next() {
41 #[clippy::version = "1.57.0"]
44 "usage of `ok()` in `let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
47 declare_lint_pass
!(MatchResultOk
=> [MATCH_RESULT_OK
]);
49 impl<'tcx
> LateLintPass
<'tcx
> for MatchResultOk
{
50 fn check_expr(&mut self, cx
: &LateContext
<'tcx
>, expr
: &'tcx Expr
<'_
>) {
51 let (let_pat
, let_expr
, ifwhile
) =
52 if let Some(higher
::IfLet { let_pat, let_expr, .. }
) = higher
::IfLet
::hir(cx
, expr
) {
53 (let_pat
, let_expr
, "if")
54 } else if let Some(higher
::WhileLet { let_pat, let_expr, .. }
) = higher
::WhileLet
::hir(expr
) {
55 (let_pat
, let_expr
, "while")
61 if let ExprKind
::MethodCall(ok_path
, result_types_0
, ..) = let_expr
.kind
; //check is expr.ok() has type Result<T,E>.ok(, _)
62 if let PatKind
::TupleStruct(QPath
::Resolved(_
, x
), y
, _
) = let_pat
.kind
; //get operation
63 if method_chain_args(let_expr
, &["ok"]).is_some(); //test to see if using ok() method use std::marker::Sized;
64 if is_type_diagnostic_item(cx
, cx
.typeck_results().expr_ty(result_types_0
), sym
::Result
);
65 if rustc_hir_pretty
::to_string(rustc_hir_pretty
::NO_ANN
, |s
| s
.print_path(x
, false)) == "Some";
69 let mut applicability
= Applicability
::MachineApplicable
;
70 let some_expr_string
= snippet_with_applicability(cx
, y
[0].span
, "", &mut applicability
);
71 let trimmed_ok
= snippet_with_applicability(cx
, let_expr
.span
.until(ok_path
.ident
.span
), "", &mut applicability
);
73 "{ifwhile} let Ok({some_expr_string}) = {}",
74 trimmed_ok
.trim().trim_end_matches('
.'
),
79 expr
.span
.with_hi(let_expr
.span
.hi()),
80 "matching on `Some` with `ok()` is redundant",
81 &format
!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),