SIGN IN SIGN UP

unnecessary_fold: lint folding over an Option's iterator (#17445)

*[View all
comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust-clippy/pull/17445)*

Fixes rust-lang/rust-clippy#1658

Folding over an `Option`'s iterator visits zero or one items, which is
`map_or` in disguise:

```rust
opt.iter().fold(init, |acc, x| f(acc, x))
// is
opt.as_ref().map_or(init, |x| f(init, x))
```

(`as_mut()` for `iter_mut()`, plain `map_or` for `into_iter()`, which
consumes the `Option`.)

This extends `unnecessary_fold` rather than adding a new lint, and only
runs when none of the existing `any`/`all`/`sum`/`product` cases fired,
so existing behavior and test expectations are unchanged.

Suggestion details:

- accumulator uses in the closure body are replaced with the `init`
expression via a multipart suggestion
- only lints when `init` is a literal or a binding of a `Copy` type, so
every suggestion is machine-applicable
- closure parameters are not accepted as `init`: with nested folds the
enclosing closure may itself be rewritten by this lint, which would
leave the copied name unresolved (covered in
`unnecessary_fold_nested.rs`)
- bails out when any rewritten span comes from a different syntax
context

changelog: [`unnecessary_fold`]: lint `fold` over an `Option`'s iterator
and suggest `map_or`
L
llogiq committed
cde6ea0eb4b31769ed5806ed31efec4795913085
Committed by GitHub <noreply@github.com> on 8/22/2026, 10:28:47 AM