]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use crate::utils::{eager_or_lazy, usage}; |
2 | use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_sugg}; | |
3 | use rustc_errors::Applicability; | |
4 | use rustc_hir as hir; | |
5 | use rustc_lint::LateContext; | |
6 | use rustc_span::sym; | |
7 | ||
8 | use super::UNNECESSARY_LAZY_EVALUATIONS; | |
9 | ||
10 | /// lint use of `<fn>_else(simple closure)` for `Option`s and `Result`s that can be | |
11 | /// replaced with `<fn>(return value of simple closure)` | |
12 | pub(super) fn check<'tcx>( | |
13 | cx: &LateContext<'tcx>, | |
14 | expr: &'tcx hir::Expr<'_>, | |
15 | args: &'tcx [hir::Expr<'_>], | |
16 | simplify_using: &str, | |
17 | ) { | |
18 | let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym::option_type); | |
19 | let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym::result_type); | |
20 | ||
21 | if is_option || is_result { | |
22 | if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { | |
23 | let body = cx.tcx.hir().body(eid); | |
24 | let body_expr = &body.value; | |
25 | ||
26 | if usage::BindingUsageFinder::are_params_used(cx, body) { | |
27 | return; | |
28 | } | |
29 | ||
30 | if eager_or_lazy::is_eagerness_candidate(cx, body_expr) { | |
31 | let msg = if is_option { | |
32 | "unnecessary closure used to substitute value for `Option::None`" | |
33 | } else { | |
34 | "unnecessary closure used to substitute value for `Result::Err`" | |
35 | }; | |
36 | let applicability = if body | |
37 | .params | |
38 | .iter() | |
39 | // bindings are checked to be unused above | |
40 | .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild)) | |
41 | { | |
42 | Applicability::MachineApplicable | |
43 | } else { | |
44 | // replacing the lambda may break type inference | |
45 | Applicability::MaybeIncorrect | |
46 | }; | |
47 | ||
48 | span_lint_and_sugg( | |
49 | cx, | |
50 | UNNECESSARY_LAZY_EVALUATIONS, | |
51 | expr.span, | |
52 | msg, | |
53 | &format!("use `{}` instead", simplify_using), | |
54 | format!( | |
55 | "{0}.{1}({2})", | |
56 | snippet(cx, args[0].span, ".."), | |
57 | simplify_using, | |
58 | snippet(cx, body_expr.span, ".."), | |
59 | ), | |
60 | applicability, | |
61 | ); | |
62 | } | |
63 | } | |
64 | } | |
65 | } |