//@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(|| { if true { v } else { v2 } }); // semicolon on if, use or_insert_with(..) m.entry(k).or_insert_with(|| { if true { v } else { v2 } }); // early return, use if let if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { if true { e.insert(v); } else { e.insert(v2); return; } } // use or_insert_with(..) m.entry(k).or_insert_with(|| { foo(); v }); // semicolon on insert and match, use or_insert_with(..) m.entry(k).or_insert_with(|| { 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) { match 0 { 0 => foo(), _ => { e.insert(v2); }, }; } // use or_insert_with m.entry(k).or_insert_with(|| { 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(|| { 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) { let Some(1) = Some(2) else { return None; }; e.insert(42); } Some(()) } fn main() {}