]>
Commit | Line | Data |
---|---|---|
f2b60f7d FG |
1 | use clippy_utils::diagnostics::span_lint_and_sugg; |
2 | use clippy_utils::source::snippet_with_applicability; | |
ed00b5ec | 3 | use clippy_utils::ty::is_type_diagnostic_item; |
f2b60f7d | 4 | use clippy_utils::visitors::is_local_used; |
ed00b5ec | 5 | use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs}; |
f2b60f7d FG |
6 | use if_chain::if_chain; |
7 | use rustc_errors::Applicability; | |
8 | use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind}; | |
9 | use rustc_lint::LateContext; | |
10 | use rustc_middle::ty::{self, UintTy}; | |
11 | use rustc_span::sym; | |
12 | ||
13 | use super::NAIVE_BYTECOUNT; | |
14 | ||
15 | pub(super) fn check<'tcx>( | |
16 | cx: &LateContext<'tcx>, | |
17 | expr: &'tcx Expr<'_>, | |
18 | filter_recv: &'tcx Expr<'_>, | |
19 | filter_arg: &'tcx Expr<'_>, | |
20 | ) { | |
21 | if_chain! { | |
22 | if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind; | |
23 | let body = cx.tcx.hir().body(body); | |
24 | if let [param] = body.params; | |
25 | if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind; | |
26 | if let ExprKind::Binary(ref op, l, r) = body.value.kind; | |
27 | if op.node == BinOpKind::Eq; | |
ed00b5ec | 28 | if is_type_diagnostic_item(cx, |
f2b60f7d | 29 | cx.typeck_results().expr_ty(filter_recv).peel_refs(), |
ed00b5ec | 30 | sym::SliceIter); |
f2b60f7d FG |
31 | let operand_is_arg = |expr| { |
32 | let expr = peel_ref_operators(cx, peel_blocks(expr)); | |
33 | path_to_local_id(expr, arg_id) | |
34 | }; | |
35 | let needle = if operand_is_arg(l) { | |
36 | r | |
37 | } else if operand_is_arg(r) { | |
38 | l | |
39 | } else { | |
40 | return; | |
41 | }; | |
42 | if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind(); | |
43 | if !is_local_used(cx, needle, arg_id); | |
44 | then { | |
45 | let haystack = if let ExprKind::MethodCall(path, receiver, [], _) = | |
46 | filter_recv.kind { | |
47 | let p = path.ident.name; | |
add651ee | 48 | if p == sym::iter || p == sym::iter_mut { |
f2b60f7d FG |
49 | receiver |
50 | } else { | |
51 | filter_recv | |
52 | } | |
53 | } else { | |
54 | filter_recv | |
55 | }; | |
56 | let mut applicability = Applicability::MaybeIncorrect; | |
57 | span_lint_and_sugg( | |
58 | cx, | |
59 | NAIVE_BYTECOUNT, | |
60 | expr.span, | |
61 | "you appear to be counting bytes the naive way", | |
62 | "consider using the bytecount crate", | |
63 | format!("bytecount::count({}, {})", | |
64 | snippet_with_applicability(cx, haystack.span, "..", &mut applicability), | |
65 | snippet_with_applicability(cx, needle.span, "..", &mut applicability)), | |
66 | applicability, | |
67 | ); | |
68 | } | |
69 | }; | |
70 | } |