`iter.last()` will drop all elements of `iter` in order, while `iter.next_back()` will drop the non-last elements of `iter` when `iter` goes out of scope since `.next_back()` does not consume its argument. When the transformation proposed by `double_ended_iterator_last` would concern an iterator whose element type has a significant drop, a note is added to warn about the possible drop order change, and the suggestion is switched from `MachineApplicable` to `MaybeIncorrect`.
92 lines
3 KiB
Rust
92 lines
3 KiB
Rust
#![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();
|
|
}
|
|
|
|
fn issue_14139() {
|
|
let mut index = [true, true, false, false, false, true].iter();
|
|
let mut subindex = index.by_ref().take(3);
|
|
let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
|
|
|
|
let mut index = [true, true, false, false, false, true].iter();
|
|
let mut subindex = index.by_ref().take(3);
|
|
let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
|
|
|
|
let mut index = [true, true, false, false, false, true].iter();
|
|
let mut subindex = index.by_ref().take(3);
|
|
let subindex = &mut subindex;
|
|
let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
|
|
|
|
let mut index = [true, true, false, false, false, true].iter();
|
|
let mut subindex = index.by_ref().take(3);
|
|
let subindex = &mut subindex;
|
|
let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
|
|
|
|
let mut index = [true, true, false, false, false, true].iter();
|
|
let (mut subindex, _) = (index.by_ref().take(3), 42);
|
|
let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
|
|
}
|
|
|
|
fn drop_order() {
|
|
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 = v.into_iter();
|
|
println!("Last element is {}", v.next_back().unwrap().0);
|
|
//~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
|
|
println!("Done");
|
|
}
|