Skip to content

Compile error after applying clippy::map_entry #13934

@hwright

Description

@hwright

Summary

After applying a clippy::map_entry suggested fix, the generated code fails to compile. Clippy appears unable to see uses of the given map from within method calls on the same struct.

Lint Name

clippy::map_entry

Reproducer

I tried this code:

use std::collections::HashMap;

struct Member {}

pub struct Foo {
    members: HashMap<u8, Member>,
}

impl Foo {
    pub fn bar(&mut self, input: u8) -> Result<(), String> {
        if self.members.contains_key(&input) {
            Err("already exists".to_string())
        } else {
            self.other();
            self.members.insert(input, Member {});
            Ok(())
        }
    }

    fn other(&self) {
        for key in self.members.keys() {
            println!("key: {}", key);
        }
    }
}

I saw this happen:

    Checking playground v0.0.1 (/playground)
warning: usage of `contains_key` followed by `insert` on a `HashMap`
  --> src/lib.rs:11:9
   |
11 | /         if self.members.contains_key(&input) {
12 | |             Err("already exists".to_string())
13 | |         } else {
14 | |             self.other();
15 | |             self.members.insert(input, Member {});
16 | |             Ok(())
17 | |         }
   | |_________^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
   = note: `#[warn(clippy::map_entry)]` on by default
help: try
   |
11 ~         if let std::collections::hash_map::Entry::Vacant(e) = self.members.entry(input) {
12 +             self.other();
13 +             e.insert(Member {});
14 +             Ok(())
15 +         } else {
16 +             Err("already exists".to_string())
17 +         }
   |

warning: `playground` (lib) generated 1 warning (run `cargo clippy --fix --lib -p playground` to apply 1 suggestion)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.46s

When applied to the original code, this suggestion fails to compile with this error:

Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/lib.rs:12:14
   |
11 |         if let std::collections::hash_map::Entry::Vacant(e) = self.members.entry(input) {
   |                                                               ------------ mutable borrow occurs here
12 |              self.other();
   |              ^^^^ immutable borrow occurs here
13 |              e.insert(Member {});
   |              - mutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground` (lib) due to 1 previous error

I expected to see this happen:
I expect clippy to not make this suggestion at all.

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

@rustbot label +l-suggestion-causes-error

Metadata

Metadata

Assignees

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