Skip to content

cargo clippy --fix for clippy::manual_retain results in broken code #13852

Open
@mschrempf

Description

@mschrempf

Summary

Running cargo clippy --fix in this example project results broken code:

 clippy-bug git:(main) cargo clippy --fix
    Checking clippy-bug v0.1.0 (/private/tmp/clippy-bug)
warning: failed to automatically apply fixes suggested by rustc to crate `clippy_bug`

after fixes were automatically applied the compiler reported errors within these files:

  * src/main.rs

This likely indicates a bug in either rustc or cargo itself,
and we would appreciate a bug report! You're likely to see
a number of compiler warnings after this message which cargo
attempted to fix but failed. If you could open an issue at
https://github.com/rust-lang/rust-clippy/issues
quoting the full output of this command we'd be very appreciative!
Note that you may be able to make some more progress in the near-term
fixing code with the `--broken-code` flag

The following errors were reported:
error[E0502]: cannot borrow `a[_]` as mutable because it is also borrowed as immutable
 --> src/main.rs:5:9
  |
5 |           a[i].retain(|&b| {
  |           ^    ------ ---- immutable borrow occurs here
  |           |    |
  |  _________|    immutable borrow later used by call
  | |
6 | |                 a[i+1]
  | |                 - first borrow occurs due to use of `a` in closure
7 | |                     .iter()
8 | |                     .any(|&c| c == b)
9 | |             });
  | |______________^ mutable borrow occurs here

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0502`.
Original diagnostics will follow.

warning: this expression can be written more simply using `.retain()`
  --> src/main.rs:5:9
   |
5  | /         a[i] = a[i]
6  | |             .iter()
7  | |             .filter(|&&b| {
8  | |                 a[i+1]
...  |
12 | |             .copied()
13 | |             .collect();
   | |______________________^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain
   = note: `#[warn(clippy::manual_retain)]` on by default
help: consider calling `.retain()` instead
   |
5  ~         a[i].retain(|&b| {
6  +                 a[i+1]
7  +                     .iter()
8  +                     .any(|&c| c == b)
9  ~             });
   |

warning: `clippy-bug` (bin "clippy-bug" test) generated 1 warning (run `cargo clippy --fix --bin "clippy-bug" --tests` to apply 1 suggestion)
warning: failed to automatically apply fixes suggested by rustc to crate `clippy_bug`

after fixes were automatically applied the compiler reported errors within these files:

  * src/main.rs

This likely indicates a bug in either rustc or cargo itself,
and we would appreciate a bug report! You're likely to see
a number of compiler warnings after this message which cargo
attempted to fix but failed. If you could open an issue at
https://github.com/rust-lang/rust-clippy/issues
quoting the full output of this command we'd be very appreciative!
Note that you may be able to make some more progress in the near-term
fixing code with the `--broken-code` flag

The following errors were reported:
error[E0502]: cannot borrow `a[_]` as mutable because it is also borrowed as immutable
 --> src/main.rs:5:9
  |
5 |           a[i].retain(|&b| {
  |           ^    ------ ---- immutable borrow occurs here
  |           |    |
  |  _________|    immutable borrow later used by call
  | |
6 | |                 a[i+1]
  | |                 - first borrow occurs due to use of `a` in closure
7 | |                     .iter()
8 | |                     .any(|&c| c == b)
9 | |             });
  | |______________^ mutable borrow occurs here

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0502`.
Original diagnostics will follow.

warning: `clippy-bug` (bin "clippy-bug") generated 1 warning (1 duplicate)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.60s

Reproducer

I tried this code in main.rs:

fn main() {
    let mut a = [vec![1,2,3,4], vec![5,6,7,8]];

    for i in 0..a.len()-1 {
        a[i] = a[i]
            .iter()
            .filter(|&&b| {
                a[i+1]
                    .iter()
                    .any(|&c| c == b)
            })
            .copied()
            .collect();
    }
}

I expected to see this happen:

  • cargo clippy --fix does not break the code

Instead, this happened:

  • cargo clippy --fix breaks the code

Version

rustc 1.83.0 (90b35a623 2024-11-26)
binary: rustc
commit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf
commit-date: 2024-11-26
host: aarch64-apple-darwin
release: 1.83.0
LLVM version: 19.1.1

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions