#![warn(clippy::manual_map)]
#![allow(
    clippy::no_effect,
    clippy::map_identity,
    clippy::unit_arg,
    clippy::match_ref_pats,
    clippy::redundant_pattern_matching,
    clippy::unnecessary_map_on_constructor,
    for_loops_over_fallibles,
    dead_code
)]

fn main() {
    Some(0).map(|_| 2);

    Some(0).map(|x| x + 1);

    Some("").map(|x| x.is_empty());

    Some(0).map(|x| !x);

    #[rustfmt::skip]
    Some(0).map(std::convert::identity);

    Some(&String::new()).map(|x| str::len(x));

    match Some(0) {
        Some(x) if false => Some(x + 1),
        _ => None,
    };

    Some([0, 1]).as_ref().map(|x| x[0]);

    Some(0).map(|x| x * 2);

    Some(String::new()).as_ref().map(|x| x.is_empty());

    Some(String::new()).as_ref().map(|x| x.len());

    Some(0).map(|x| x + x);

    #[warn(clippy::option_map_unit_fn)]
    match &mut Some(String::new()) {
        Some(x) => Some(x.push_str("")),
        None => None,
    };

    #[allow(clippy::option_map_unit_fn)]
    {
        Some(String::new()).as_mut().map(|x| x.push_str(""));
    }

    Some(String::new()).as_ref().map(|x| x.len());

    Some(String::new()).as_ref().map(|x| x.is_empty());

    Some((0, 1, 2)).map(|(x, y, z)| x + y + z);

    Some([1, 2, 3]).map(|[first, ..]| first);

    Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x));

    match Some((String::new(), 0)) {
        Some((ref x, y)) => Some((y, x)),
        None => None,
    };

    match Some(Some(0)) {
        Some(Some(_)) | Some(None) => Some(0),
        None => None,
    };

    match Some(Some((0, 1))) {
        Some(Some((x, 1))) => Some(x),
        _ => None,
    };

    // #6795
    fn f1() -> Result<(), ()> {
        let _ = match Some(Ok(())) {
            Some(x) => Some(x?),
            None => None,
        };
        Ok(())
    }

    for &x in Some(Some(true)).iter() {
        let _ = match x {
            Some(x) => Some(if x { continue } else { x }),
            None => None,
        };
    }

    // #6797
    let x1 = (Some(String::new()), 0);
    let x2 = x1.0;
    match x2 {
        Some(x) => Some((x, x1.1)),
        None => None,
    };

    struct S1 {
        x: Option<String>,
        y: u32,
    }
    impl S1 {
        fn f(self) -> Option<(String, u32)> {
            match self.x {
                Some(x) => Some((x, self.y)),
                None => None,
            }
        }
    }

    // #6811
    match Some(0) {
        Some(x) => Some(vec![x]),
        None => None,
    };

    // Don't lint, coercion
    let x: Option<Vec<&[u8]>> = match Some(()) {
        Some(_) => Some(vec![b"1234"]),
        None => None,
    };

    option_env!("").map(String::from);

    // #6819
    async fn f2(x: u32) -> u32 {
        x
    }

    async fn f3() {
        match Some(0) {
            Some(x) => Some(f2(x).await),
            None => None,
        };
    }

    // #6847
    if let Some(_) = Some(0) {
        Some(0)
    } else { Some(0).map(|x| x + 1) };

    if true {
        Some(0)
    } else { Some(0).map(|x| x + 1) };

    // #6967
    const fn f4() {
        match Some(0) {
            Some(x) => Some(x + 1),
            None => None,
        };
    }

    // #7077
    let s = &String::new();
    #[allow(clippy::needless_match)]
    let _: Option<&str> = match Some(s) {
        Some(s) => Some(s),
        None => None,
    };
}
