use std::cell::Cell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::{Hash, Hasher}; use std::rc::Rc; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::Relaxed; use std::sync::Arc; struct Key(AtomicUsize); impl Clone for Key { fn clone(&self) -> Self { Key(AtomicUsize::new(self.0.load(Relaxed))) } } impl PartialEq for Key { fn eq(&self, other: &Self) -> bool { self.0.load(Relaxed) == other.0.load(Relaxed) } } impl Eq for Key {} impl Hash for Key { fn hash(&self, h: &mut H) { self.0.load(Relaxed).hash(h); } } fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { //~^ ERROR: mutable key type //~| NOTE: `-D clippy::mutable-key-type` implied by `-D warnings` //~| ERROR: mutable key type let _other: HashMap = HashMap::new(); //~^ ERROR: mutable key type m.keys().cloned().collect() } fn this_is_ok(_m: &mut HashMap) {} // Raw pointers are hashed by the address they point to, so it doesn't matter if they point to a // type with interior mutability. See: // - clippy issue: https://github.com/rust-lang/rust-clippy/issues/6745 // - std lib: https://github.com/rust-lang/rust/blob/1.54.0/library/core/src/hash/mod.rs#L717-L736 // So these are OK: fn raw_ptr_is_ok(_m: &mut HashMap<*const Key, ()>) {} fn raw_mut_ptr_is_ok(_m: &mut HashMap<*mut Key, ()>) {} #[allow(unused)] trait Trait { type AssociatedType; fn trait_fn(&self, set: HashSet); } fn generics_are_ok_too(_m: &mut HashSet) { // nothing to see here, move along } fn tuples(_m: &mut HashMap<((), U), ()>) {} fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} //~^ ERROR: mutable key type fn main() { let _ = should_not_take_this_arg(&mut HashMap::new(), 1); this_is_ok(&mut HashMap::new()); tuples::(&mut HashMap::new()); tuples::<()>(&mut HashMap::new()); tuples_bad::<()>(&mut HashMap::new()); raw_ptr_is_ok(&mut HashMap::new()); raw_mut_ptr_is_ok(&mut HashMap::new()); let _map = HashMap::, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::<&mut Cell, usize>::new(); //~^ ERROR: mutable key type // Collection types from `std` who's impl of `Hash` or `Ord` delegate their type parameters let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::, ()>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::>>, usize>::new(); //~^ ERROR: mutable key type // Smart pointers from `std` who's impl of `Hash` or `Ord` delegate their type parameters let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type let _map = HashMap::>, usize>::new(); //~^ ERROR: mutable key type // Not interior mutability let _map = HashMap::<&mut usize, usize>::new(); let _map = HashMap::, usize>::new(); }