@@ -50,6 +50,7 @@ mod manual_next_back;
5050mod manual_ok_or;
5151mod manual_saturating_arithmetic;
5252mod manual_str_repeat;
53+ mod manual_try_fold;
5354mod map_clone;
5455mod map_collect_result_unit;
5556mod map_err_ignore;
@@ -3286,6 +3287,30 @@ declare_clippy_lint! {
32863287 "calling `.drain(..).collect()` to move all elements into a new collection"
32873288}
32883289
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+
32893314pub struct Methods {
32903315 avoid_breaking_exported_api : bool ,
32913316 msrv : Msrv ,
@@ -3416,7 +3441,8 @@ impl_lint_pass!(Methods => [
34163441 CLEAR_WITH_DRAIN ,
34173442 MANUAL_NEXT_BACK ,
34183443 UNNECESSARY_LITERAL_UNWRAP ,
3419- DRAIN_COLLECT
3444+ DRAIN_COLLECT ,
3445+ MANUAL_TRY_FOLD ,
34203446] ) ;
34213447
34223448/// Extracts a method call name, args, and `Span` of the method name.
@@ -3709,7 +3735,10 @@ impl Methods {
37093735 Some ( ( "cloned" , recv2, [ ] , _, _) ) => iter_overeager_cloned:: check ( cx, expr, recv, recv2, false , true ) ,
37103736 _ => { } ,
37113737 } ,
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+ } ,
37133742 ( "for_each" , [ _] ) => {
37143743 if let Some ( ( "inspect" , _, [ _] , span2, _) ) = method_call ( recv) {
37153744 inspect_for_each:: check ( cx, expr, span2) ;
0 commit comments