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