rust-lang / rust-lang/rust-clippy

`iter_mut` isn't less confusing when `.into_iter().map(DerefMut::deref_mut)`

Open
#12,230 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Summary

I find this lint's suggestion in this case actually produces more confusing code, for me. It also seems unnecessary, because the type transformation clearly goes from &mut T to &mut U, meaning that there is no misunderstanding about what is happening here, voiding the actual reason for the lint: that it was done unintentionally.

I guess this is highly subjective and maybe not worth the time? In many cases I can simply accept my repo has a nonstandard style with respect to Rust, but this one seemed highly unusual. I have made .into_iter() vs. .iter() mistakes before, but they were pure thrashing, and usually the main issue I see people have with .iter() is where using iter() is actually the culprit, and is the result of code that resembles this:

let v1 = v0.iter().collect(); // Vec<&T>
let v2 = v1.iter().collect(); // Vec<&&T>
let v3 = v2.iter().collect(); // Vec<&&&T>
Reproducer

I tried this code:

impl<'cx, T: Enlist> List<'cx, T> {
    /* ...whole lotta code... */

    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        let list_cells_slice /*: &mut [ListCell<T>] */ = self.as_cells_mut();
        let iterable_cells /*: IterMut<'_, ListCell<T>> */  = list_cells_slice.into_iter();
        let iterable_inners /*: impl Iterator<Item = &mut T */  = iterable_cells.map(DerefMut::deref_mut);
        iterable_inners
    }
}

I got this:

warning: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `slice`
   --> pgrx/src/list/flat_list.rs:225:47
    |
225 |         let iterable_cells = list_cells_slice.into_iter();
    |                                               ^^^^^^^^^ help: call directly: `iter_mut`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref

I find this code to be more confusing. Well, this sample may not be that confusing, but that is because this sample was deliberately annotated to be less so, as I tried to work out what the diagnostics issue was. To more clearly show my problem, the actual code in context that generated this lint (and twice, actually):

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.as_cells().into_iter().map(Deref::deref)
    }

    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        self.as_cells_mut().into_iter().map(DerefMut::deref_mut)
    }

I deliberately used into_iter() here so as to not create the "stuttering" as_cells().iter() and as_cells_mut().iter_mut() inside these two fn, making it easier to see the real differences. And the initial suggestion, in my not-quite-caffeinated state, read to me as a suggestion to write:

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.as_cells().iter()
    }

    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        self.as_cells_mut().iter_mut()
    }

That... simply doesn't work. In fact, I initially had this open as a false positive report for that suggestion before I actually looked closer, and realized the span hadn't indicated the map as well. 😅

Version
rustc 1.75.0 (82e1608df 2023-12-21)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-unknown-linux-gnu
release: 1.75.0
LLVM version: 17.0.6
Additional Labels

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

Start by locating the Clippy implementation and tests for the into_iter_on_ref lint, then reproduce the diagnostic with the examples in this issue. Compare the suggested span and wording with the intended Deref/DerefMut transformation; done means the issue's concern is resolved with regression coverage or a documented decision.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools, 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.