//@needs-asm-support

#![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);
        }
    }
}

// Don't suggest when it would cause `MutexGuard` to be held across an await point.
mod issue_16173 {
    use std::collections::HashMap;
    use std::sync::Mutex;

    async fn f() {}

    async fn foo() {
        let mu_map = Mutex::new(HashMap::new());
        if !mu_map.lock().unwrap().contains_key(&0) {
            f().await;
            mu_map.lock().unwrap().insert(0, 0);
        }

        if mu_map.lock().unwrap().contains_key(&1) {
            todo!();
        } else {
            mu_map.lock().unwrap().insert(1, 42);
            todo!();
            f().await;
        }
    }
}

fn main() {}

fn issue15781(m: &mut std::collections::HashMap<i32, i32>, k: i32, v: i32) {
    fn very_important_fn() {}
    m.entry(k).or_insert_with(|| {
        //~^ map_entry
        #[cfg(test)]
        very_important_fn();
        v
    });
}
