Skip to content

Commit 713f632

Browse files
authored
Unrolled build for rust-lang#139773
Rollup merge of rust-lang#139773 - thaliaarchi:vec-into-iter-last, r=workingjubilee Implement `Iterator::last` for `vec::IntoIter` Avoid iterating everything when we have random access to the last element.
2 parents 7295b08 + cbdd713 commit 713f632

7 files changed

+53
-9
lines changed

library/alloc/src/vec/into_iter.rs

+5
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,11 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
258258
self.len()
259259
}
260260

261+
#[inline]
262+
fn last(mut self) -> Option<T> {
263+
self.next_back()
264+
}
265+
261266
#[inline]
262267
fn next_chunk<const N: usize>(&mut self) -> Result<[T; N], core::array::IntoIter<T, N>> {
263268
let mut raw_ary = [const { MaybeUninit::uninit() }; N];

library/std/src/sys/args/common.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ impl Iterator for Args {
4949
}
5050

5151
#[inline]
52-
fn last(mut self) -> Option<OsString> {
53-
self.iter.next_back()
52+
fn last(self) -> Option<OsString> {
53+
self.iter.last()
5454
}
5555

5656
#[inline]

src/tools/clippy/tests/ui/double_ended_iterator_last.fixed

+14-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ fn issue_14139() {
8484
}
8585

8686
fn drop_order() {
87+
struct DropDeIterator(std::vec::IntoIter<S>);
88+
impl Iterator for DropDeIterator {
89+
type Item = S;
90+
fn next(&mut self) -> Option<Self::Item> {
91+
self.0.next()
92+
}
93+
}
94+
impl DoubleEndedIterator for DropDeIterator {
95+
fn next_back(&mut self) -> Option<Self::Item> {
96+
self.0.next_back()
97+
}
98+
}
99+
87100
struct S(&'static str);
88101
impl std::ops::Drop for S {
89102
fn drop(&mut self) {
@@ -92,7 +105,7 @@ fn drop_order() {
92105
}
93106

94107
let v = vec![S("one"), S("two"), S("three")];
95-
let mut v = v.into_iter();
108+
let mut v = DropDeIterator(v.into_iter());
96109
println!("Last element is {}", v.next_back().unwrap().0);
97110
//~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
98111
println!("Done");

src/tools/clippy/tests/ui/double_ended_iterator_last.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ fn issue_14139() {
8484
}
8585

8686
fn drop_order() {
87+
struct DropDeIterator(std::vec::IntoIter<S>);
88+
impl Iterator for DropDeIterator {
89+
type Item = S;
90+
fn next(&mut self) -> Option<Self::Item> {
91+
self.0.next()
92+
}
93+
}
94+
impl DoubleEndedIterator for DropDeIterator {
95+
fn next_back(&mut self) -> Option<Self::Item> {
96+
self.0.next_back()
97+
}
98+
}
99+
87100
struct S(&'static str);
88101
impl std::ops::Drop for S {
89102
fn drop(&mut self) {
@@ -92,7 +105,7 @@ fn drop_order() {
92105
}
93106

94107
let v = vec![S("one"), S("two"), S("three")];
95-
let v = v.into_iter();
108+
let v = DropDeIterator(v.into_iter());
96109
println!("Last element is {}", v.last().unwrap().0);
97110
//~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
98111
println!("Done");

src/tools/clippy/tests/ui/double_ended_iterator_last.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ LL | let _ = DeIterator.last();
1818
| help: try: `next_back()`
1919

2020
error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
21-
--> tests/ui/double_ended_iterator_last.rs:96:36
21+
--> tests/ui/double_ended_iterator_last.rs:109:36
2222
|
2323
LL | println!("Last element is {}", v.last().unwrap().0);
2424
| ^^^^^^^^
2525
|
2626
= note: this change will alter drop order which may be undesirable
2727
help: try
2828
|
29-
LL ~ let mut v = v.into_iter();
29+
LL ~ let mut v = DropDeIterator(v.into_iter());
3030
LL ~ println!("Last element is {}", v.next_back().unwrap().0);
3131
|
3232

src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ fn main() {
1111
}
1212

1313
fn drop_order() {
14+
struct DropDeIterator(std::vec::IntoIter<S>);
15+
impl Iterator for DropDeIterator {
16+
type Item = S;
17+
fn next(&mut self) -> Option<Self::Item> {
18+
self.0.next()
19+
}
20+
}
21+
impl DoubleEndedIterator for DropDeIterator {
22+
fn next_back(&mut self) -> Option<Self::Item> {
23+
self.0.next_back()
24+
}
25+
}
26+
1427
struct S(&'static str);
1528
impl std::ops::Drop for S {
1629
fn drop(&mut self) {
@@ -19,7 +32,7 @@ fn drop_order() {
1932
}
2033

2134
let v = vec![S("one"), S("two"), S("three")];
22-
let v = (v.into_iter(), 42);
35+
let v = (DropDeIterator(v.into_iter()), 42);
2336
println!("Last element is {}", v.0.last().unwrap().0);
2437
//~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
2538
println!("Done");

src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
2-
--> tests/ui/double_ended_iterator_last_unfixable.rs:23:36
2+
--> tests/ui/double_ended_iterator_last_unfixable.rs:36:36
33
|
44
LL | println!("Last element is {}", v.0.last().unwrap().0);
55
| ^^^^------
@@ -8,7 +8,7 @@ LL | println!("Last element is {}", v.0.last().unwrap().0);
88
|
99
= note: this change will alter drop order which may be undesirable
1010
note: this must be made mutable to use `.next_back()`
11-
--> tests/ui/double_ended_iterator_last_unfixable.rs:23:36
11+
--> tests/ui/double_ended_iterator_last_unfixable.rs:36:36
1212
|
1313
LL | println!("Last element is {}", v.0.last().unwrap().0);
1414
| ^^^

0 commit comments

Comments
 (0)