Skip to content

Commit 47e4e77

Browse files
committed
Auto merge of rust-lang#85340 - the8472:no-inplaceiterable-on-peekable, r=yaahc
remove InPlaceIterable marker from Peekable due to unsoundness The unsoundness is not in Peekable per se, it rather is due to the interaction between Peekable being able to hold an extra item and vec::IntoIter's clone implementation shortening the allocation. An alternative solution would be to change IntoIter's clone implementation to keep enough spare capacity available. fixes rust-lang#85322
2 parents fdaa765 + 0b6a3da commit 47e4e77

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

alloc/benches/vec.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,6 @@ fn bench_in_place_recycle(b: &mut Bencher) {
468468
.enumerate()
469469
.map(|(idx, e)| idx.wrapping_add(e))
470470
.fuse()
471-
.peekable()
472471
.collect::<Vec<usize>>(),
473472
);
474473
});

alloc/tests/vec.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,6 @@ fn test_from_iter_specialization_with_iterator_adapters() {
10021002
.zip(std::iter::repeat(1usize))
10031003
.map(|(a, b)| a + b)
10041004
.map_while(Option::Some)
1005-
.peekable()
10061005
.skip(1)
10071006
.map(|e| if e != usize::MAX { Ok(std::num::NonZeroUsize::new(e)) } else { Err(()) });
10081007
assert_in_place_trait(&iter);
@@ -1095,6 +1094,18 @@ fn test_from_iter_specialization_panic_during_drop_leaks() {
10951094
}
10961095
}
10971096

1097+
// regression test for issue #85322. Peekable previously implemented InPlaceIterable,
1098+
// but due to an interaction with IntoIter's current Clone implementation it failed to uphold
1099+
// the contract.
1100+
#[test]
1101+
fn test_collect_after_iterator_clone() {
1102+
let v = vec![0; 5];
1103+
let mut i = v.into_iter().map(|i| i + 1).peekable();
1104+
i.peek();
1105+
let v = i.clone().collect::<Vec<_>>();
1106+
assert_eq!(v, [1, 1, 1, 1, 1]);
1107+
assert!(v.len() <= v.capacity());
1108+
}
10981109
#[test]
10991110
fn test_cow_from() {
11001111
let borrowed: &[_] = &["borrowed", "(slice)"];

core/src/iter/adapters/peekable.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
1+
use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen};
22
use crate::ops::{ControlFlow, Try};
33

44
/// An iterator with a `peek()` that returns an optional reference to the next
@@ -356,6 +356,3 @@ where
356356
unsafe { SourceIter::as_inner(&mut self.iter) }
357357
}
358358
}
359-
360-
#[unstable(issue = "none", feature = "inplace_iteration")]
361-
unsafe impl<I: InPlaceIterable> InPlaceIterable for Peekable<I> {}

0 commit comments

Comments
 (0)