]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
Auto merge of #99609 - workingjubilee:lossy-unix-strerror, r=thomcc
[rust.git] / src / tools / clippy / clippy_lints / src / matches / match_wild_err_arm.rs
1 use clippy_utils::diagnostics::span_lint_and_note;
2 use clippy_utils::macros::{is_panic, root_macro_call};
3 use clippy_utils::ty::is_type_diagnostic_item;
4 use clippy_utils::visitors::is_local_used;
5 use clippy_utils::{is_wild, peel_blocks_with_stmt};
6 use rustc_hir::{Arm, Expr, PatKind};
7 use rustc_lint::LateContext;
8 use rustc_span::symbol::{kw, sym};
9
10 use super::MATCH_WILD_ERR_ARM;
11
12 pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'tcx>]) {
13     let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs();
14     if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
15         for arm in arms {
16             if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
17                 let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false));
18                 if path_str == "Err" {
19                     let mut matching_wild = inner.iter().any(is_wild);
20                     let mut ident_bind_name = kw::Underscore;
21                     if !matching_wild {
22                         // Looking for unused bindings (i.e.: `_e`)
23                         for pat in inner.iter() {
24                             if let PatKind::Binding(_, id, ident, None) = pat.kind {
25                                 if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) {
26                                     ident_bind_name = ident.name;
27                                     matching_wild = true;
28                                 }
29                             }
30                         }
31                     }
32                     if_chain! {
33                         if matching_wild;
34                         if let Some(macro_call) = root_macro_call(peel_blocks_with_stmt(arm.body).span);
35                         if is_panic(cx, macro_call.def_id);
36                         then {
37                             // `Err(_)` or `Err(_e)` arm with `panic!` found
38                             span_lint_and_note(cx,
39                                 MATCH_WILD_ERR_ARM,
40                                 arm.pat.span,
41                                 &format!("`Err({})` matches all errors", ident_bind_name),
42                                 None,
43                                 "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable",
44                             );
45                         }
46                     }
47                 }
48             }
49         }
50     }
51 }