Skip to content

explicit_iter_loop: x.iter_mut() vs &mut *x #11074

Closed
@dtolnay

Description

@dtolnay

Summary

I have a hard time being confident that Clippy's suggestion in the following case constitutes an improvement to the code:

-     for xi in x.iter_mut() {
+     for xi in &mut *x {

Could we revisit whether it is worth suggesting a change in this case?

In cases where the suggestion is for xi in x {, I am fully supportive of the lint. Obviously for xi in x is a clear improvement over for xi in x.iter_mut() (modulo the restriction from #8585 being turned on).

I am also generally supportive of for xi in &mut x.

But the case of for xi in &mut *x starts to be over the line for me in symbol soup.

Lint Name

explicit_iter_loop

Reproducer

#![warn(clippy::pedantic)]

pub fn imul(x: &mut Vec<u64>, y: u64) {
    // Multiply iteratively over all elements, adding the carry each time.
    let mut carry = 0;
    for xi in x.iter_mut() {
        carry = scalar::imul(xi, y, carry);
    }

    // Overflow of value, add to end.
    if carry != 0 {
        x.push(carry);
    }
}

mod scalar {
    pub fn imul(_x: &mut u64, _y: u64, _carry: u64) -> u64 {
        todo!()
    }
}
$ cargo clippy

warning: it is more concise to loop over references to containers instead of using explicit iteration methods
 --> src/main.rs:6:15
  |
6 |     for xi in x.iter_mut() {
  |               ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *x`

This is a case where neither for xi in x { nor for xi in &mut x { compiles.

error[E0382]: borrow of moved value: `x`
   --> src/main.rs:12:9
    |
3   | pub fn imul(x: &mut Vec<u64>, y: u64) {
    |             - move occurs because `x` has type `&mut Vec<u64>`, which does not implement the `Copy` trait
...
6   |     for xi in x {
    |               - `x` moved due to this implicit call to `.into_iter()`
...
12  |         x.push(carry);
    |         ^^^^^^^^^^^^^ value borrowed here after move
    |
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
error[E0277]: `Vec<u64>` is not an iterator
 --> src/main.rs:6:15
  |
6 |     for xi in &mut x {
  |               ^^^^^^ `Vec<u64>` is not an iterator; try calling `.into_iter()` or `.iter()`
  |
  = help: the trait `Iterator` is not implemented for `Vec<u64>`
  = note: required for `&mut Vec<u64>` to implement `Iterator`
  = note: 1 redundant requirement hidden
  = note: required for `&mut &mut Vec<u64>` to implement `Iterator`
  = note: required for `&mut &mut Vec<u64>` to implement `IntoIterator`
help: consider removing the leading `&`-reference
  |
6 -     for xi in &mut x {
6 +     for xi in x {
  |

Version

rustc 1.72.0-nightly (839e9a6e1 2023-07-02)
binary: rustc
commit-hash: 839e9a6e1210934fd24b15548b811a97c77138fc
commit-date: 2023-07-02
host: x86_64-unknown-linux-gnu
release: 1.72.0-nightly
LLVM version: 16.0.5

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't have

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions