@@ -50,6 +50,7 @@ mod manual_next_back;
50
50
mod manual_ok_or;
51
51
mod manual_saturating_arithmetic;
52
52
mod manual_str_repeat;
53
+ mod manual_try_fold;
53
54
mod map_clone;
54
55
mod map_collect_result_unit;
55
56
mod map_err_ignore;
@@ -3286,6 +3287,30 @@ declare_clippy_lint! {
3286
3287
"calling `.drain(..).collect()` to move all elements into a new collection"
3287
3288
}
3288
3289
3290
+ declare_clippy_lint ! {
3291
+ /// ### What it does
3292
+ /// Checks for usage of `Iterator::fold` with a type that implements `Try`.
3293
+ ///
3294
+ /// ### Why is this bad?
3295
+ /// This is better represented with `try_fold`, but this has one major difference: It will
3296
+ /// short-circuit on failure. *This is almost always what you want*. This can also open the door
3297
+ /// for additional optimizations as well, as rustc can guarantee the function is never
3298
+ /// called on `None`, `Err`, etc., alleviating otherwise necessary checks.
3299
+ ///
3300
+ /// ### Example
3301
+ /// ```rust
3302
+ /// vec![1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i));
3303
+ /// ```
3304
+ /// Use instead:
3305
+ /// ```rust
3306
+ /// vec![1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i));
3307
+ /// ```
3308
+ #[ clippy:: version = "1.72.0" ]
3309
+ pub MANUAL_TRY_FOLD ,
3310
+ perf,
3311
+ "checks for usage of `Iterator::fold` with a type that implements `Try`"
3312
+ }
3313
+
3289
3314
pub struct Methods {
3290
3315
avoid_breaking_exported_api : bool ,
3291
3316
msrv : Msrv ,
@@ -3416,7 +3441,8 @@ impl_lint_pass!(Methods => [
3416
3441
CLEAR_WITH_DRAIN ,
3417
3442
MANUAL_NEXT_BACK ,
3418
3443
UNNECESSARY_LITERAL_UNWRAP ,
3419
- DRAIN_COLLECT
3444
+ DRAIN_COLLECT ,
3445
+ MANUAL_TRY_FOLD ,
3420
3446
] ) ;
3421
3447
3422
3448
/// Extracts a method call name, args, and `Span` of the method name.
@@ -3709,7 +3735,10 @@ impl Methods {
3709
3735
Some ( ( "cloned" , recv2, [ ] , _, _) ) => iter_overeager_cloned:: check ( cx, expr, recv, recv2, false , true ) ,
3710
3736
_ => { } ,
3711
3737
} ,
3712
- ( "fold" , [ init, acc] ) => unnecessary_fold:: check ( cx, expr, init, acc, span) ,
3738
+ ( "fold" , [ init, acc] ) => {
3739
+ manual_try_fold:: check ( cx, expr, init, acc, call_span, & self . msrv ) ;
3740
+ unnecessary_fold:: check ( cx, expr, init, acc, span) ;
3741
+ } ,
3713
3742
( "for_each" , [ _] ) => {
3714
3743
if let Some ( ( "inspect" , _, [ _] , span2, _) ) = method_call ( recv) {
3715
3744
inspect_for_each:: check ( cx, expr, span2) ;
0 commit comments