]>
git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/bytecount.rs
4 use syntax
::ast
::{Name, UintTy}
;
5 use utils
::{contains_name
, get_pat_name
, match_type
, paths
, single_segment_path
, snippet
, span_lint_and_sugg
,
8 /// **What it does:** Checks for naive byte counts
10 /// **Why is this bad?** The [`bytecount`](https://crates.io/crates/bytecount)
11 /// crate has methods to count your bytes faster, especially for large slices.
13 /// **Known problems:** If you have predominantly small slices, the
14 /// `bytecount::count(..)` method may actually be slower. However, if you can
15 /// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
16 /// faster in those cases.
21 /// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead
23 declare_clippy_lint
! {
26 "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values"
29 #[derive(Copy, Clone)]
32 impl LintPass
for ByteCount
{
33 fn get_lints(&self) -> LintArray
{
34 lint_array
!(NAIVE_BYTECOUNT
)
38 impl<'a
, 'tcx
> LateLintPass
<'a
, 'tcx
> for ByteCount
{
39 fn check_expr(&mut self, cx
: &LateContext
, expr
: &Expr
) {
41 if let ExprMethodCall(ref count
, _
, ref count_args
) = expr
.node
;
42 if count
.name
== "count";
43 if count_args
.len() == 1;
44 if let ExprMethodCall(ref filter
, _
, ref filter_args
) = count_args
[0].node
;
45 if filter
.name
== "filter";
46 if filter_args
.len() == 2;
47 if let ExprClosure(_
, _
, body_id
, _
, _
) = filter_args
[1].node
;
49 let body
= cx
.tcx
.hir
.body(body_id
);
51 if body
.arguments
.len() == 1;
52 if let Some(argname
) = get_pat_name(&body
.arguments
[0].pat
);
53 if let ExprBinary(ref op
, ref l
, ref r
) = body
.value
.node
;
56 walk_ptrs_ty(cx
.tables
.expr_ty(&filter_args
[0])),
59 let needle
= match get_path_name(l
) {
60 Some(name
) if check_arg(name
, argname
, r
) => r
,
61 _
=> match get_path_name(r
) {
62 Some(name
) if check_arg(name
, argname
, l
) => l
,
66 if ty
::TyUint(UintTy
::U8
) != walk_ptrs_ty(cx
.tables
.expr_ty(needle
)).sty
{
69 let haystack
= if let ExprMethodCall(ref path
, _
, ref args
) =
72 if (p
== "iter" || p
== "iter_mut") && args
.len() == 1 {
80 span_lint_and_sugg(cx
,
83 "You appear to be counting bytes the naive way",
84 "Consider using the bytecount crate",
85 format
!("bytecount::count({}, {})",
86 snippet(cx
, haystack
.span
, ".."),
87 snippet(cx
, needle
.span
, "..")));
95 fn check_arg(name
: Name
, arg
: Name
, needle
: &Expr
) -> bool
{
96 name
== arg
&& !contains_name(name
, needle
)
99 fn get_path_name(expr
: &Expr
) -> Option
<Name
> {
101 ExprBox(ref e
) | ExprAddrOf(_
, ref e
) | ExprUnary(UnOp
::UnDeref
, ref e
) => get_path_name(e
),
102 ExprBlock(ref b
) => if b
.stmts
.is_empty() {
103 b
.expr
.as_ref().and_then(|p
| get_path_name(p
))
107 ExprPath(ref qpath
) => single_segment_path(qpath
).map(|ps
| ps
.name
),