summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/manual_filter_map.fixed
blob: 831323089e7f27cb74cfea61a7f5f29585618380 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::manual_filter_map)]
#![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure

fn main() {
    // is_some(), unwrap()
    let _ = (0..).filter_map(|a| to_opt(a));

    // ref pattern, expect()
    let _ = (0..).filter_map(|a| to_opt(a));

    // is_ok(), unwrap_or()
    let _ = (0..).filter_map(|a| to_res(a).ok());

    let _ = (1..5)
        .filter_map(|y| *to_ref(to_opt(y)));
    let _ = (1..5)
        .filter_map(|y| *to_ref(to_opt(y)));

    let _ = (1..5)
        .filter_map(|y| to_ref(to_res(y)).ok());
    let _ = (1..5)
        .filter_map(|y| to_ref(to_res(y)).ok());
}

#[rustfmt::skip]
fn simple_equal() {
    iter::<Option<&u8>>().find_map(|x| x.cloned());
    iter::<&Option<&u8>>().find_map(|x| x.cloned());
    iter::<&Option<String>>().find_map(|x| x.as_deref());
    iter::<Option<&String>>().find_map(|y| to_ref(y).cloned());

    iter::<Result<u8, ()>>().find_map(|x| x.ok());
    iter::<&Result<u8, ()>>().find_map(|x| x.ok());
    iter::<&&Result<u8, ()>>().find_map(|x| x.ok());
    iter::<Result<&u8, ()>>().find_map(|x| x.cloned().ok());
    iter::<&Result<&u8, ()>>().find_map(|x| x.cloned().ok());
    iter::<&Result<String, ()>>().find_map(|x| x.as_deref().ok());
    iter::<Result<&String, ()>>().find_map(|y| to_ref(y).cloned().ok());
}

fn no_lint() {
    // no shared code
    let _ = (0..).filter(|n| *n > 1).map(|n| n + 1);

    // very close but different since filter() provides a reference
    let _ = (0..).filter(|n| to_opt(n).is_some()).map(|a| to_opt(a).unwrap());

    // similar but different
    let _ = (0..).filter(|n| to_opt(n).is_some()).map(|n| to_res(n).unwrap());
    let _ = (0..)
        .filter(|n| to_opt(n).map(|n| n + 1).is_some())
        .map(|a| to_opt(a).unwrap());
}

fn iter<T>() -> impl Iterator<Item = T> {
    std::iter::empty()
}

fn to_opt<T>(_: T) -> Option<T> {
    unimplemented!()
}

fn to_res<T>(_: T) -> Result<T, ()> {
    unimplemented!()
}

fn to_ref<'a, T>(_: T) -> &'a T {
    unimplemented!()
}

struct Issue8920<'a> {
    option_field: Option<String>,
    result_field: Result<String, ()>,
    ref_field: Option<&'a usize>,
}

fn issue_8920() {
    let mut vec = vec![Issue8920 {
        option_field: Some(String::from("str")),
        result_field: Ok(String::from("str")),
        ref_field: Some(&1),
    }];

    let _ = vec
        .iter()
        .filter_map(|f| f.option_field.clone());

    let _ = vec
        .iter()
        .filter_map(|f| f.ref_field.cloned());

    let _ = vec
        .iter()
        .filter_map(|f| f.ref_field.copied());

    let _ = vec
        .iter()
        .filter_map(|f| f.result_field.clone().ok());

    let _ = vec
        .iter()
        .filter_map(|f| f.result_field.as_ref().ok());

    let _ = vec
        .iter()
        .filter_map(|f| f.result_field.as_deref().ok());

    let _ = vec
        .iter_mut()
        .filter_map(|f| f.result_field.as_mut().ok());

    let _ = vec
        .iter_mut()
        .filter_map(|f| f.result_field.as_deref_mut().ok());

    let _ = vec
        .iter()
        .filter_map(|f| f.result_field.to_owned().ok());
}