| //@needs-asm-support |
| |
| #![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] |
| #![warn(clippy::map_entry)] |
| |
| use std::arch::asm; |
| use std::collections::HashMap; |
| use std::hash::Hash; |
| |
| macro_rules! m { |
| ($e:expr) => {{ $e }}; |
| } |
| |
| macro_rules! insert { |
| ($map:expr, $key:expr, $val:expr) => { |
| $map.insert($key, $val) |
| }; |
| } |
| |
| fn foo() {} |
| |
| fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMap<K, V>, k: K, k2: K, v: V, v2: V) { |
| // or_insert(v) |
| m.entry(k).or_insert(v); |
| |
| // semicolon on insert, use or_insert_with(..) |
| m.entry(k).or_insert_with(|| { |
| //~^ map_entry |
| if true { |
| v |
| } else { |
| v2 |
| } |
| }); |
| |
| // semicolon on if, use or_insert_with(..) |
| m.entry(k).or_insert_with(|| { |
| //~^ map_entry |
| if true { |
| v |
| } else { |
| v2 |
| } |
| }); |
| |
| // early return, use if let |
| if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { |
| //~^ map_entry |
| if true { |
| e.insert(v); |
| } else { |
| e.insert(v2); |
| return; |
| } |
| } |
| |
| // use or_insert_with(..) |
| m.entry(k).or_insert_with(|| { |
| //~^ map_entry |
| foo(); |
| v |
| }); |
| |
| // semicolon on insert and match, use or_insert_with(..) |
| m.entry(k).or_insert_with(|| { |
| //~^ map_entry |
| match 0 { |
| 1 if true => { |
| v |
| }, |
| _ => { |
| v2 |
| }, |
| } |
| }); |
| |
| // one branch doesn't insert, use if let |
| if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { |
| //~^ map_entry |
| match 0 { |
| 0 => foo(), |
| _ => { |
| e.insert(v2); |
| }, |
| }; |
| } |
| |
| // use or_insert_with |
| m.entry(k).or_insert_with(|| { |
| //~^ map_entry |
| foo(); |
| match 0 { |
| 0 if false => { |
| v |
| }, |
| 1 => { |
| foo(); |
| v |
| }, |
| 2 | 3 => { |
| for _ in 0..2 { |
| foo(); |
| } |
| if true { |
| v |
| } else { |
| v2 |
| } |
| }, |
| _ => { |
| v2 |
| }, |
| } |
| }); |
| |
| // ok, insert in loop |
| if !m.contains_key(&k) { |
| for _ in 0..2 { |
| m.insert(k, v); |
| } |
| } |
| |
| // macro_expansion test, use or_insert(..) |
| m.entry(m!(k)).or_insert_with(|| m!(v)); |
| |
| // ok, map used before insertion |
| if !m.contains_key(&k) { |
| let _ = m.len(); |
| m.insert(k, v); |
| } |
| |
| // ok, inline asm |
| if !m.contains_key(&k) { |
| unsafe { asm!("nop") } |
| m.insert(k, v); |
| } |
| |
| // ok, different keys. |
| if !m.contains_key(&k) { |
| m.insert(k2, v); |
| } |
| |
| // ok, different maps |
| if !m.contains_key(&k) { |
| m2.insert(k, v); |
| } |
| |
| // ok, insert in macro |
| if !m.contains_key(&k) { |
| insert!(m, k, v); |
| } |
| |
| // or_insert_with. Partial move of a local declared in the closure is ok. |
| m.entry(k).or_insert_with(|| { |
| //~^ map_entry |
| let x = (String::new(), String::new()); |
| let _ = x.0; |
| v |
| }); |
| } |
| |
| // Issue 10331 |
| // do not suggest a bad expansion because the compiler unrolls the first |
| // occurrence of the loop |
| pub fn issue_10331() { |
| let mut m = HashMap::new(); |
| let mut i = 0; |
| let mut x = 0; |
| while !m.contains_key(&x) { |
| m.insert(x, i); |
| i += 1; |
| x += 1; |
| } |
| } |
| |
| /// Issue 11935 |
| /// Do not suggest using entries if the map is used inside the `insert` expression. |
| pub fn issue_11935() { |
| let mut counts: HashMap<u64, u64> = HashMap::new(); |
| if !counts.contains_key(&1) { |
| counts.insert(1, 1); |
| } else { |
| counts.insert(1, counts.get(&1).unwrap() + 1); |
| } |
| } |
| |
| fn issue12489(map: &mut HashMap<u64, u64>) -> Option<()> { |
| if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) { |
| //~^ map_entry |
| let Some(1) = Some(2) else { |
| return None; |
| }; |
| e.insert(42); |
| } |
| Some(()) |
| } |
| |
| mod issue13934 { |
| use std::collections::HashMap; |
| |
| struct Member {} |
| |
| pub struct Foo { |
| members: HashMap<u8, Member>, |
| } |
| |
| impl Foo { |
| pub fn should_also_not_cause_lint(&mut self, input: u8) { |
| if self.members.contains_key(&input) { |
| todo!(); |
| } else { |
| self.other(); |
| self.members.insert(input, Member {}); |
| } |
| } |
| |
| fn other(&self) {} |
| } |
| } |
| |
| fn issue11976() { |
| let mut hashmap = std::collections::HashMap::new(); |
| if !hashmap.contains_key(&0) { |
| let _ = || hashmap.get(&0); |
| hashmap.insert(0, 0); |
| } |
| } |
| |
| mod issue14449 { |
| use std::collections::BTreeMap; |
| |
| pub struct Meow { |
| map: BTreeMap<String, String>, |
| } |
| |
| impl Meow { |
| fn pet(&self, _key: &str, _v: u32) -> u32 { |
| 42 |
| } |
| } |
| |
| pub fn f(meow: &Meow, x: String) { |
| if meow.map.contains_key(&x) { |
| let _ = meow.pet(&x, 1); |
| } else { |
| let _ = meow.pet(&x, 0); |
| } |
| } |
| } |
| |
| fn main() {} |