11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: source:: snippet_with_applicability;
33use clippy_utils:: ty:: match_type;
4- use clippy_utils:: { contains_name, get_pat_name, paths, single_segment_path} ;
4+ use clippy_utils:: visitors:: LocalUsedVisitor ;
5+ use clippy_utils:: { path_to_local_id, paths, peel_ref_operators, remove_blocks, strip_pat_refs} ;
56use if_chain:: if_chain;
67use rustc_errors:: Applicability ;
7- use rustc_hir:: { BinOpKind , BorrowKind , Expr , ExprKind , UnOp } ;
8+ use rustc_hir:: { BinOpKind , Expr , ExprKind , PatKind } ;
89use rustc_lint:: { LateContext , LateLintPass } ;
910use rustc_middle:: ty:: { self , UintTy } ;
1011use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1112use rustc_span:: sym;
12- use rustc_span:: Symbol ;
1313
1414declare_clippy_lint ! {
1515 /// **What it does:** Checks for naive byte counts
@@ -38,42 +38,43 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);
3838impl < ' tcx > LateLintPass < ' tcx > for ByteCount {
3939 fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
4040 if_chain ! {
41- if let ExprKind :: MethodCall ( count, _, count_args , _) = expr. kind;
41+ if let ExprKind :: MethodCall ( count, _, [ count_recv ] , _) = expr. kind;
4242 if count. ident. name == sym!( count) ;
43- if count_args. len( ) == 1 ;
44- if let ExprKind :: MethodCall ( filter, _, filter_args, _) = count_args[ 0 ] . kind;
43+ if let ExprKind :: MethodCall ( filter, _, [ filter_recv, filter_arg] , _) = count_recv. kind;
4544 if filter. ident. name == sym!( filter) ;
46- if filter_args. len( ) == 2 ;
47- if let ExprKind :: Closure ( _, _, body_id, _, _) = filter_args[ 1 ] . kind;
45+ if let ExprKind :: Closure ( _, _, body_id, _, _) = filter_arg. kind;
4846 let body = cx. tcx. hir( ) . body( body_id) ;
49- if body . params . len ( ) == 1 ;
50- if let Some ( argname ) = get_pat_name ( body . params [ 0 ] . pat) ;
47+ if let [ param ] = body . params ;
48+ if let PatKind :: Binding ( _ , arg_id , _ , _ ) = strip_pat_refs ( param . pat) . kind ;
5149 if let ExprKind :: Binary ( ref op, l, r) = body. value. kind;
5250 if op. node == BinOpKind :: Eq ;
5351 if match_type( cx,
54- cx. typeck_results( ) . expr_ty( & filter_args [ 0 ] ) . peel_refs( ) ,
52+ cx. typeck_results( ) . expr_ty( filter_recv ) . peel_refs( ) ,
5553 & paths:: SLICE_ITER ) ;
54+ let operand_is_arg = |expr| {
55+ let expr = peel_ref_operators( cx, remove_blocks( expr) ) ;
56+ path_to_local_id( expr, arg_id)
57+ } ;
58+ let needle = if operand_is_arg( l) {
59+ r
60+ } else if operand_is_arg( r) {
61+ l
62+ } else {
63+ return ;
64+ } ;
65+ if ty:: Uint ( UintTy :: U8 ) == * cx. typeck_results( ) . expr_ty( needle) . peel_refs( ) . kind( ) ;
66+ if !LocalUsedVisitor :: new( cx, arg_id) . check_expr( needle) ;
5667 then {
57- let needle = match get_path_name( l) {
58- Some ( name) if check_arg( name, argname, r) => r,
59- _ => match get_path_name( r) {
60- Some ( name) if check_arg( name, argname, l) => l,
61- _ => { return ; }
62- }
63- } ;
64- if ty:: Uint ( UintTy :: U8 ) != * cx. typeck_results( ) . expr_ty( needle) . peel_refs( ) . kind( ) {
65- return ;
66- }
6768 let haystack = if let ExprKind :: MethodCall ( path, _, args, _) =
68- filter_args [ 0 ] . kind {
69+ filter_recv . kind {
6970 let p = path. ident. name;
7071 if ( p == sym:: iter || p == sym!( iter_mut) ) && args. len( ) == 1 {
7172 & args[ 0 ]
7273 } else {
73- & filter_args [ 0 ]
74+ & filter_recv
7475 }
7576 } else {
76- & filter_args [ 0 ]
77+ & filter_recv
7778 } ;
7879 let mut applicability = Applicability :: MaybeIncorrect ;
7980 span_lint_and_sugg(
@@ -91,24 +92,3 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
9192 } ;
9293 }
9394}
94-
95- fn check_arg ( name : Symbol , arg : Symbol , needle : & Expr < ' _ > ) -> bool {
96- name == arg && !contains_name ( name, needle)
97- }
98-
99- fn get_path_name ( expr : & Expr < ' _ > ) -> Option < Symbol > {
100- match expr. kind {
101- ExprKind :: Box ( e) | ExprKind :: AddrOf ( BorrowKind :: Ref , _, e) | ExprKind :: Unary ( UnOp :: Deref , e) => {
102- get_path_name ( e)
103- } ,
104- ExprKind :: Block ( b, _) => {
105- if b. stmts . is_empty ( ) {
106- b. expr . as_ref ( ) . and_then ( |p| get_path_name ( p) )
107- } else {
108- None
109- }
110- } ,
111- ExprKind :: Path ( ref qpath) => single_segment_path ( qpath) . map ( |ps| ps. ident . name ) ,
112- _ => None ,
113- }
114- }
0 commit comments