rust-lang / rust-lang/rust-clippy

Bad suggestion and false positive `redundant_iter_cloned`

Open
#15,725 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-false-positive P-medium
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Summary

After updating nightly rust today, I got a bad lint for the code at https://github.com/jj-vcs/jj/tree/a5b61b2cc331e8b8c7636b706ca1be9f1a33815b.

See https://github.com/jj-vcs/jj/pull/7557 for details (mostly copied below)

Lint Name

redundant_iter_cloned

Reproducer

I tried this code:

 let commits: std::collections::HashMap<CommitId, _> = bookmark_list_items
            .iter()
            .filter_map(|item| item.primary.target().added_ids().next())  // Iterator of type &CommitId
            .cloned()
            .map(|commit_id| {
                store
                    .get_commit(&commit_id)
                    .map(|commit| (commit_id, commit.store_commit().clone()))
            })
            .try_collect()?;

I saw this happen:

warning: unneeded cloning of iterator items
   --> cli/src/commands/bookmark/list.rs:251:19
    |
251 |           commits = bookmark_list_items
    |  ___________________^
252 | |             .iter()
253 | |             .filter_map(|item| item.primary.target().added_ids().next())
254 | |             .cloned()
...   |
258 | |                     .map(|commit| (commit_id, commit.store_commit().clone()))
259 | |             })
    | |______________^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_iter_cloned
    = note: `#[warn(clippy::redundant_iter_cloned)]` on by default
help: try
    |
253 ~             .filter_map(|item| item.primary.target().added_ids().next())
254 +             .map(|commit_id| {
255 +                 store
256 +                     .get_commit(&commit_id)
257 +                     .map(|commit| (commit_id, commit.store_commit().clone()))
258 +             })
    |

Following the suggestion and removing the .cloned() results in an error:

The error:

error[E0277]: a value of type `std::collections::HashMap<jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>>` cannot be built from an iterator over elements of type `(&jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>)`
    --> cli/src/commands/bookmark/list.rs:259:14
     |
 259 |             .try_collect()?;
     |              ^^^^^^^^^^^ value of type `std::collections::HashMap<jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>>` cannot be built from `std::iter::Iterator<Item=(&jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>)>`
     |
     = help: the trait `FromIterator<(&jj_lib::backend::CommitId, std::sync::Arc<_>)>` is not implemented for `std::collections::HashMap<jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>>`
             but trait `FromIterator<(jj_lib::backend::CommitId, std::sync::Arc<_>)>` is implemented for it
     = help: for that trait implementation, expected `jj_lib::backend::CommitId`, found `&jj_lib::backend::CommitId`
     = note: required for `Result<HashMap<CommitId, Arc<Commit>>, BackendError>` to implement `FromIterator<Result<(&CommitId, Arc<Commit>), BackendError>>`
note: required by a bound in `itertools::Itertools::try_collect`
    --> /Users/ilyagr/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.14.0/src/lib.rs:2381:23
     |
2378 |     fn try_collect<T, U, E>(self) -> Result<U, E>
     |        ----------- required by a bound in this associated function
...
2381 |         Result<U, E>: FromIterator<Result<T, E>>,
     |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Itertools::try_collect`
     = note: the full name for the type has been written to '/Users/ilyagr/dev/jj/target/debug/deps/jj_cli-442101cf9493e967.long-type-2991360816845051416.txt'
     = note: consider using `--verbose` to print the full type name to the console

The following diff satisfies clippy, but it doesn't seem much better than the original version, and certainly differs from what clippy suggested.

diff --git a/cli/src/commands/bookmark/list.rs b/cli/src/commands/bookmark/list.rs
index bd362dc9bf..bb9f26bc07 100644
--- a/cli/src/commands/bookmark/list.rs
+++ b/cli/src/commands/bookmark/list.rs
@@ -251,11 +251,10 @@
         commits = bookmark_list_items
             .iter()
             .filter_map(|item| item.primary.target().added_ids().next())
-            .cloned()
             .map(|commit_id| {
                 store
-                    .get_commit(&commit_id)
-                    .map(|commit| (commit_id, commit.store_commit().clone()))
+                    .get_commit(commit_id)
+                    .map(|commit| (commit_id.clone(), commit.store_commit().clone()))
             })
             .try_collect()?;
     }
Version
rustc 1.92.0-nightly (0be8e1608 2025-09-19)
binary: rustc
commit-hash: 0be8e16088894483a7012c5026c3247c14a0c3c2
commit-date: 2025-09-19
host: aarch64-apple-darwin
release: 1.92.0-nightly
LLVM version: 21.1.1
Additional Labels

I-suggestion-causes-error

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the report with the Rust snippet and inspect the redundant_iter_cloned lint entry point. Compare its suggestion with cli/src/commands/bookmark/list.rs and verify that the suggested rewrite compiles while preserving the HashMap<CommitId, ...> collection. Done means the false positive and erroneous suggestion are covered and no longer occur.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.