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
|
#![warn(clippy::double_ended_iterator_last)]
// Typical case
pub fn last_arg(s: &str) -> Option<&str> {
s.split(' ').next_back() //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
}
fn main() {
// General case
struct DeIterator;
impl Iterator for DeIterator {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
Some(())
}
}
impl DoubleEndedIterator for DeIterator {
fn next_back(&mut self) -> Option<Self::Item> {
Some(())
}
}
let _ = DeIterator.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
// Should not apply to other methods of Iterator
let _ = DeIterator.count();
// Should not apply to simple iterators
struct SimpleIterator;
impl Iterator for SimpleIterator {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
Some(())
}
}
let _ = SimpleIterator.last();
// Should not apply to custom implementations of last()
struct CustomLast;
impl Iterator for CustomLast {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
Some(())
}
fn last(self) -> Option<Self::Item> {
Some(())
}
}
impl DoubleEndedIterator for CustomLast {
fn next_back(&mut self) -> Option<Self::Item> {
Some(())
}
}
let _ = CustomLast.last();
}
// Should not be linted because applying the lint would move the original iterator. This can only be
// linted if the iterator is used thereafter.
fn issue_14139() {
let mut index = [true, true, false, false, false, true].iter();
let subindex = index.by_ref().take(3);
let _ = subindex.last();
let _ = index.next();
let mut index = [true, true, false, false, false, true].iter();
let mut subindex = index.by_ref().take(3);
let _ = subindex.last();
let _ = index.next();
let mut index = [true, true, false, false, false, true].iter();
let mut subindex = index.by_ref().take(3);
let subindex = &mut subindex;
let _ = subindex.last();
let _ = index.next();
let mut index = [true, true, false, false, false, true].iter();
let mut subindex = index.by_ref().take(3);
let subindex = &mut subindex;
let _ = subindex.last();
let _ = index.next();
let mut index = [true, true, false, false, false, true].iter();
let (subindex, _) = (index.by_ref().take(3), 42);
let _ = subindex.last();
let _ = index.next();
let mut index = [true, true, false, false, false, true].iter();
let subindex = (index.by_ref().take(3), 42);
let _ = subindex.0.last();
let _ = index.next();
}
fn drop_order() {
struct DropDeIterator(std::vec::IntoIter<S>);
impl Iterator for DropDeIterator {
type Item = S;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
impl DoubleEndedIterator for DropDeIterator {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
struct S(&'static str);
impl std::ops::Drop for S {
fn drop(&mut self) {
println!("Dropping {}", self.0);
}
}
let v = vec![S("one"), S("two"), S("three")];
let mut v = DropDeIterator(v.into_iter());
println!("Last element is {}", v.next_back().unwrap().0);
//~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
let v = vec![S("four"), S("five"), S("six")];
let mut v = (DropDeIterator(v.into_iter()), 42);
println!("Last element is {}", v.0.next_back().unwrap().0);
//~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
println!("Done");
}
fn issue_14444() {
let mut squares = vec![];
let last_square = [1, 2, 3]
.into_iter()
.map(|x| {
squares.push(x * x);
Some(x * x)
})
.last();
}
|