### What it does Checks for sets/maps with mutable key types. ### Why is this bad? All of `HashMap`, `HashSet`, `BTreeMap` and `BtreeSet` rely on either the hash or the order of keys be unchanging, so having types with interior mutability is a bad idea. ### Known problems #### False Positives It's correct to use a struct that contains interior mutability as a key, when its implementation of `Hash` or `Ord` doesn't access any of the interior mutable types. However, this lint is unable to recognize this, so it will often cause false positives in theses cases. The `bytes` crate is a great example of this. #### False Negatives For custom `struct`s/`enum`s, this lint is unable to check for interior mutability behind indirection. For example, `struct BadKey<'a>(&'a Cell)` will be seen as immutable and cause a false negative if its implementation of `Hash`/`Ord` accesses the `Cell`. This lint does check a few cases for indirection. Firstly, using some standard library types (`Option`, `Result`, `Box`, `Rc`, `Arc`, `Vec`, `VecDeque`, `BTreeMap` and `BTreeSet`) directly as keys (e.g. in `HashMap>, ()>`) **will** trigger the lint, because the impls of `Hash`/`Ord` for these types directly call `Hash`/`Ord` on their contained type. Secondly, the implementations of `Hash` and `Ord` for raw pointers (`*const T` or `*mut T`) apply only to the **address** of the contained value. Therefore, interior mutability behind raw pointers (e.g. in `HashSet<*mut Cell>`) can't impact the value of `Hash` or `Ord`, and therefore will not trigger this link. For more info, see issue [#6745](https://github.com/rust-lang/rust-clippy/issues/6745). ### Example ``` use std::cmp::{PartialEq, Eq}; use std::collections::HashSet; use std::hash::{Hash, Hasher}; use std::sync::atomic::AtomicUsize; struct Bad(AtomicUsize); impl PartialEq for Bad { fn eq(&self, rhs: &Self) -> bool { .. ; unimplemented!(); } } impl Eq for Bad {} impl Hash for Bad { fn hash(&self, h: &mut H) { .. ; unimplemented!(); } } fn main() { let _: HashSet = HashSet::new(); } ```