@@ -40,6 +40,7 @@ mod string_extend_chars;
40
40
mod suspicious_map;
41
41
mod uninit_assumed_init;
42
42
mod unnecessary_filter_map;
43
+ mod unnecessary_fold;
43
44
mod unnecessary_lazy_eval;
44
45
mod unwrap_used;
45
46
mod useless_asref;
@@ -53,7 +54,7 @@ use if_chain::if_chain;
53
54
use rustc_ast:: ast;
54
55
use rustc_errors:: Applicability ;
55
56
use rustc_hir as hir;
56
- use rustc_hir:: { PatKind , TraitItem , TraitItemKind } ;
57
+ use rustc_hir:: { TraitItem , TraitItemKind } ;
57
58
use rustc_lint:: { LateContext , LateLintPass , Lint , LintContext } ;
58
59
use rustc_middle:: lint:: in_external_macro;
59
60
use rustc_middle:: ty:: { self , TraitRef , Ty , TyS } ;
@@ -67,10 +68,9 @@ use crate::utils::eager_or_lazy::is_lazyness_candidate;
67
68
use crate :: utils:: usage:: mutated_variables;
68
69
use crate :: utils:: {
69
70
contains_return, contains_ty, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of,
70
- is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath, match_trait_method,
71
- match_type, meets_msrv, method_calls, method_chain_args, path_to_local_id, paths, remove_blocks, return_ty,
72
- single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
73
- span_lint_and_help, span_lint_and_sugg, strip_pat_refs, SpanlessEq ,
71
+ is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath, match_type, meets_msrv,
72
+ method_calls, method_chain_args, paths, return_ty, single_segment_path, snippet, snippet_with_applicability,
73
+ snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq ,
74
74
} ;
75
75
76
76
declare_clippy_lint ! {
@@ -1736,7 +1736,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1736
1736
[ "collect" , "cloned" ] => iter_cloned_collect:: check ( cx, expr, arg_lists[ 1 ] ) ,
1737
1737
[ "as_ref" ] => useless_asref:: check ( cx, expr, "as_ref" , arg_lists[ 0 ] ) ,
1738
1738
[ "as_mut" ] => useless_asref:: check ( cx, expr, "as_mut" , arg_lists[ 0 ] ) ,
1739
- [ "fold" , ..] => lint_unnecessary_fold ( cx, expr, arg_lists[ 0 ] , method_spans[ 0 ] ) ,
1739
+ [ "fold" , ..] => unnecessary_fold :: check ( cx, expr, arg_lists[ 0 ] , method_spans[ 0 ] ) ,
1740
1740
[ "filter_map" , ..] => {
1741
1741
unnecessary_filter_map:: check ( cx, expr, arg_lists[ 0 ] ) ;
1742
1742
filter_map_identity:: check ( cx, expr, arg_lists[ 0 ] , method_spans[ 0 ] ) ;
@@ -2324,94 +2324,6 @@ fn lint_expect_fun_call(
2324
2324
) ;
2325
2325
}
2326
2326
2327
- fn lint_unnecessary_fold ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , fold_args : & [ hir:: Expr < ' _ > ] , fold_span : Span ) {
2328
- fn check_fold_with_op (
2329
- cx : & LateContext < ' _ > ,
2330
- expr : & hir:: Expr < ' _ > ,
2331
- fold_args : & [ hir:: Expr < ' _ > ] ,
2332
- fold_span : Span ,
2333
- op : hir:: BinOpKind ,
2334
- replacement_method_name : & str ,
2335
- replacement_has_args : bool ,
2336
- ) {
2337
- if_chain ! {
2338
- // Extract the body of the closure passed to fold
2339
- if let hir:: ExprKind :: Closure ( _, _, body_id, _, _) = fold_args[ 2 ] . kind;
2340
- let closure_body = cx. tcx. hir( ) . body( body_id) ;
2341
- let closure_expr = remove_blocks( & closure_body. value) ;
2342
-
2343
- // Check if the closure body is of the form `acc <op> some_expr(x)`
2344
- if let hir:: ExprKind :: Binary ( ref bin_op, ref left_expr, ref right_expr) = closure_expr. kind;
2345
- if bin_op. node == op;
2346
-
2347
- // Extract the names of the two arguments to the closure
2348
- if let [ param_a, param_b] = closure_body. params;
2349
- if let PatKind :: Binding ( _, first_arg_id, ..) = strip_pat_refs( & param_a. pat) . kind;
2350
- if let PatKind :: Binding ( _, second_arg_id, second_arg_ident, _) = strip_pat_refs( & param_b. pat) . kind;
2351
-
2352
- if path_to_local_id( left_expr, first_arg_id) ;
2353
- if replacement_has_args || path_to_local_id( right_expr, second_arg_id) ;
2354
-
2355
- then {
2356
- let mut applicability = Applicability :: MachineApplicable ;
2357
- let sugg = if replacement_has_args {
2358
- format!(
2359
- "{replacement}(|{s}| {r})" ,
2360
- replacement = replacement_method_name,
2361
- s = second_arg_ident,
2362
- r = snippet_with_applicability( cx, right_expr. span, "EXPR" , & mut applicability) ,
2363
- )
2364
- } else {
2365
- format!(
2366
- "{replacement}()" ,
2367
- replacement = replacement_method_name,
2368
- )
2369
- } ;
2370
-
2371
- span_lint_and_sugg(
2372
- cx,
2373
- UNNECESSARY_FOLD ,
2374
- fold_span. with_hi( expr. span. hi( ) ) ,
2375
- // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
2376
- "this `.fold` can be written more succinctly using another method" ,
2377
- "try" ,
2378
- sugg,
2379
- applicability,
2380
- ) ;
2381
- }
2382
- }
2383
- }
2384
-
2385
- // Check that this is a call to Iterator::fold rather than just some function called fold
2386
- if !match_trait_method ( cx, expr, & paths:: ITERATOR ) {
2387
- return ;
2388
- }
2389
-
2390
- assert ! (
2391
- fold_args. len( ) == 3 ,
2392
- "Expected fold_args to have three entries - the receiver, the initial value and the closure"
2393
- ) ;
2394
-
2395
- // Check if the first argument to .fold is a suitable literal
2396
- if let hir:: ExprKind :: Lit ( ref lit) = fold_args[ 1 ] . kind {
2397
- match lit. node {
2398
- ast:: LitKind :: Bool ( false ) => {
2399
- check_fold_with_op ( cx, expr, fold_args, fold_span, hir:: BinOpKind :: Or , "any" , true )
2400
- } ,
2401
- ast:: LitKind :: Bool ( true ) => {
2402
- check_fold_with_op ( cx, expr, fold_args, fold_span, hir:: BinOpKind :: And , "all" , true )
2403
- } ,
2404
- ast:: LitKind :: Int ( 0 , _) => {
2405
- check_fold_with_op ( cx, expr, fold_args, fold_span, hir:: BinOpKind :: Add , "sum" , false )
2406
- } ,
2407
- ast:: LitKind :: Int ( 1 , _) => {
2408
- check_fold_with_op ( cx, expr, fold_args, fold_span, hir:: BinOpKind :: Mul , "product" , false )
2409
- } ,
2410
- _ => ( ) ,
2411
- }
2412
- }
2413
- }
2414
-
2415
2327
fn derefs_to_slice < ' tcx > (
2416
2328
cx : & LateContext < ' tcx > ,
2417
2329
expr : & ' tcx hir:: Expr < ' tcx > ,
0 commit comments