about summary refs log tree commit diff
path: root/src/tools/clippy/tests/ui/needless_collect.fixed
blob: b09efe9888f50f29fca14627298ab1f7bf8c9ec6 (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#![allow(
    unused,
    clippy::needless_if,
    clippy::suspicious_map,
    clippy::iter_count,
    clippy::manual_contains
)]

use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList};

#[warn(clippy::needless_collect)]
#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)]
fn main() {
    let sample = [1; 5];
    let len = sample.iter().count();
    //~^ needless_collect
    if sample.iter().next().is_none() {
        //~^ needless_collect
        // Empty
    }
    sample.iter().cloned().any(|x| x == 1);
    //~^ needless_collect
    // #7164 HashMap's and BTreeMap's `len` usage should not be linted
    sample.iter().map(|x| (x, x)).collect::<HashMap<_, _>>().len();
    sample.iter().map(|x| (x, x)).collect::<BTreeMap<_, _>>().len();

    sample.iter().map(|x| (x, x)).next().is_none();
    //~^ needless_collect
    sample.iter().map(|x| (x, x)).next().is_none();
    //~^ needless_collect

    // Notice the `HashSet`--this should not be linted
    sample.iter().collect::<HashSet<_>>().len();
    // Neither should this
    sample.iter().collect::<BTreeSet<_>>().len();

    sample.iter().count();
    //~^ needless_collect
    sample.iter().next().is_none();
    //~^ needless_collect
    sample.iter().cloned().any(|x| x == 1);
    //~^ needless_collect
    sample.iter().any(|x| x == &1);
    //~^ needless_collect

    // `BinaryHeap` doesn't have `contains` method
    sample.iter().count();
    //~^ needless_collect
    sample.iter().next().is_none();
    //~^ needless_collect

    // Don't lint string from str
    let _ = ["", ""].into_iter().collect::<String>().is_empty();

    let _ = sample.iter().next().is_none();
    //~^ needless_collect
    let _ = sample.iter().any(|x| x == &0);
    //~^ needless_collect

    struct VecWrapper<T>(Vec<T>);
    impl<T> core::ops::Deref for VecWrapper<T> {
        type Target = Vec<T>;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }
    impl<T> IntoIterator for VecWrapper<T> {
        type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
        type Item = <Vec<T> as IntoIterator>::Item;
        fn into_iter(self) -> Self::IntoIter {
            self.0.into_iter()
        }
    }
    impl<T> FromIterator<T> for VecWrapper<T> {
        fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
            Self(Vec::from_iter(iter))
        }
    }

    let _ = sample.iter().next().is_none();
    //~^ needless_collect
    let _ = sample.iter().any(|x| x == &0);
    //~^ needless_collect

    #[allow(clippy::double_parens)]
    {
        Vec::<u8>::new().extend((0..10));
        //~^ needless_collect
        foo((0..10));
        //~^ needless_collect
        bar((0..10).collect::<Vec<_>>(), (0..10));
        //~^ needless_collect
        baz((0..10), (), ('a'..='z'))
        //~^ needless_collect
    }

    let values = [1, 2, 3, 4];
    let mut out = vec![];
    values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>();
    let _y = values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine

    // Don't write a warning if we call `clone()` on the iterator
    // https://github.com/rust-lang/rust-clippy/issues/13430
    let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect();
    let _cloned = my_collection.into_iter().clone();
    let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect();
    let my_iter = my_collection.into_iter();
    let _cloned = my_iter.clone();
    // Same for `as_slice()`, for same reason.
    let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect();
    let _sliced = my_collection.into_iter().as_slice();
    let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect();
    let my_iter = my_collection.into_iter();
    let _sliced = my_iter.as_slice();
    // Assignment outside of main scope
    {
        let x;
        {
            let xxx: Vec<()> = vec![()].into_iter().map(|()| {}).collect();
            x = xxx.into_iter();
            for i in x.as_slice() {}
        }
    }
}

fn foo(_: impl IntoIterator<Item = usize>) {}
fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}

mod issue9191 {
    use std::cell::Cell;
    use std::collections::HashSet;
    use std::hash::Hash;
    use std::marker::PhantomData;
    use std::ops::Deref;

    fn captures_ref_mut(xs: Vec<i32>, mut ys: HashSet<i32>) {
        if xs.iter().map(|x| ys.remove(x)).collect::<Vec<_>>().contains(&true) {
            todo!()
        }
    }

    #[derive(Debug, Clone)]
    struct MyRef<'a>(PhantomData<&'a mut Cell<HashSet<i32>>>, *mut Cell<HashSet<i32>>);

    impl MyRef<'_> {
        fn new(target: &mut Cell<HashSet<i32>>) -> Self {
            MyRef(PhantomData, target)
        }

        fn get(&mut self) -> &mut Cell<HashSet<i32>> {
            unsafe { &mut *self.1 }
        }
    }

    fn captures_phantom(xs: Vec<i32>, mut ys: Cell<HashSet<i32>>) {
        let mut ys_ref = MyRef::new(&mut ys);
        if xs
            .iter()
            .map({
                let mut ys_ref = ys_ref.clone();
                move |x| ys_ref.get().get_mut().remove(x)
            })
            .collect::<Vec<_>>()
            .contains(&true)
        {
            todo!()
        }
    }
}

pub fn issue8055(v: impl IntoIterator<Item = i32>) -> Result<impl Iterator<Item = i32>, usize> {
    let mut zeros = 0;

    let res: Vec<_> = v
        .into_iter()
        .filter(|i| {
            if *i == 0 {
                zeros += 1
            };
            *i != 0
        })
        .collect();

    if zeros != 0 {
        return Err(zeros);
    }
    Ok(res.into_iter())
}

mod issue8055_regression {
    struct Foo<T> {
        inner: T,
        marker: core::marker::PhantomData<Self>,
    }

    impl<T: Iterator> Iterator for Foo<T> {
        type Item = T::Item;
        fn next(&mut self) -> Option<Self::Item> {
            self.inner.next()
        }
    }

    fn foo() {
        Foo {
            inner: [].iter(),
            marker: core::marker::PhantomData,
        }
        .collect::<Vec<&i32>>()
        .len();
    }
}