Auto merge of #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 #85322
This commit is contained in:
bors 2021-05-19 21:50:45 +00:00
commit df70463ea5
3 changed files with 13 additions and 6 deletions

View file

@ -468,7 +468,6 @@ fn bench_in_place_recycle(b: &mut Bencher) {
.enumerate()
.map(|(idx, e)| idx.wrapping_add(e))
.fuse()
.peekable()
.collect::<Vec<usize>>(),
);
});

View file

@ -1002,7 +1002,6 @@ fn test_from_iter_specialization_with_iterator_adapters() {
.zip(std::iter::repeat(1usize))
.map(|(a, b)| a + b)
.map_while(Option::Some)
.peekable()
.skip(1)
.map(|e| if e != usize::MAX { Ok(std::num::NonZeroUsize::new(e)) } else { Err(()) });
assert_in_place_trait(&iter);
@ -1095,6 +1094,18 @@ fn test_from_iter_specialization_panic_during_drop_leaks() {
}
}
// regression test for issue #85322. Peekable previously implemented InPlaceIterable,
// but due to an interaction with IntoIter's current Clone implementation it failed to uphold
// the contract.
#[test]
fn test_collect_after_iterator_clone() {
let v = vec![0; 5];
let mut i = v.into_iter().map(|i| i + 1).peekable();
i.peek();
let v = i.clone().collect::<Vec<_>>();
assert_eq!(v, [1, 1, 1, 1, 1]);
assert!(v.len() <= v.capacity());
}
#[test]
fn test_cow_from() {
let borrowed: &[_] = &["borrowed", "(slice)"];

View file

@ -1,4 +1,4 @@
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen};
use crate::ops::{ControlFlow, Try};
/// An iterator with a `peek()` that returns an optional reference to the next
@ -356,6 +356,3 @@ where
unsafe { SourceIter::as_inner(&mut self.iter) }
}
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<I: InPlaceIterable> InPlaceIterable for Peekable<I> {}