diff options
| author | The 8472 <git@infinite-source.de> | 2025-01-04 19:26:58 +0100 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2025-01-16 17:50:04 -0800 |
| commit | 8a7dc215b02e6b4c2dd890e750dceadeaf077f7d (patch) | |
| tree | a0ed7d5d377d1702d75964a651cfdd41e7fe4d0d | |
| parent | fe9b9751fa54a5871b87cd36a582f9b7b06123fd (diff) | |
| download | rust-8a7dc215b02e6b4c2dd890e750dceadeaf077f7d.tar.gz rust-8a7dc215b02e6b4c2dd890e750dceadeaf077f7d.zip | |
do not in-place-iterate over flatmap/flatten
The implementation is unsound when a partially consumed iterator has some elements buffered in the front/back parts and cloning the Iterator removes the capacity from the backing vec::IntoIter. (cherry picked from commit 3d871b3ced0af12a84e3d17060399ca1af8d7bc1)
| -rw-r--r-- | library/alloc/tests/vec.rs | 25 | ||||
| -rw-r--r-- | library/core/src/iter/adapters/flatten.rs | 34 |
2 files changed, 8 insertions, 51 deletions
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 84679827ba1..474ea7fe56b 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1204,22 +1204,16 @@ fn test_from_iter_specialization_with_iterator_adapters() { #[test] fn test_in_place_specialization_step_up_down() { fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {} - let src = vec![[0u8; 4]; 256]; + + let src = vec![0u8; 1024]; let srcptr = src.as_ptr(); - let src_cap = src.capacity(); - let iter = src.into_iter().flatten(); + let src_bytes = src.capacity(); + let iter = src.into_iter().array_chunks::<4>(); assert_in_place_trait(&iter); let sink = iter.collect::<Vec<_>>(); let sinkptr = sink.as_ptr(); - assert_eq!(srcptr as *const u8, sinkptr); - assert_eq!(src_cap * 4, sink.capacity()); - - let iter = sink.into_iter().array_chunks::<4>(); - assert_in_place_trait(&iter); - let sink = iter.collect::<Vec<_>>(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr, sinkptr); - assert_eq!(src_cap, sink.capacity()); + assert_eq!(srcptr.addr(), sinkptr.addr()); + assert_eq!(src_bytes, sink.capacity() * 4); let mut src: Vec<u8> = Vec::with_capacity(17); let src_bytes = src.capacity(); @@ -1236,13 +1230,6 @@ fn test_in_place_specialization_step_up_down() { let sink: Vec<[u8; 2]> = iter.collect(); assert_eq!(sink.len(), 8); assert!(sink.capacity() <= 25); - - let src = vec![[0u8; 4]; 256]; - let srcptr = src.as_ptr(); - let iter = src.into_iter().flat_map(|a| a.into_iter().map(|b| b.wrapping_add(1))); - assert_in_place_trait(&iter); - let sink = iter.collect::<Vec<_>>(); - assert_eq!(srcptr as *const u8, sink.as_ptr()); } #[test] diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 0023b46031f..9b9353b800a 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,7 +1,7 @@ use crate::iter::adapters::SourceIter; use crate::iter::{ - Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, Once, - OnceWith, TrustedFused, TrustedLen, + Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, Map, Once, OnceWith, + TrustedFused, TrustedLen, }; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; @@ -158,21 +158,6 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I, U, F> InPlaceIterable for FlatMap<I, U, F> -where - I: InPlaceIterable, - U: BoundedSize + IntoIterator, -{ - const EXPAND_BY: Option<NonZero<usize>> = const { - match (I::EXPAND_BY, U::UPPER_BOUND) { - (Some(m), Some(n)) => m.checked_mul(n), - _ => None, - } - }; - const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY; -} - -#[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl<I, U, F> SourceIter for FlatMap<I, U, F> where I: SourceIter + TrustedFused, @@ -387,21 +372,6 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I> InPlaceIterable for Flatten<I> -where - I: InPlaceIterable + Iterator, - <I as Iterator>::Item: IntoIterator + BoundedSize, -{ - const EXPAND_BY: Option<NonZero<usize>> = const { - match (I::EXPAND_BY, I::Item::UPPER_BOUND) { - (Some(m), Some(n)) => m.checked_mul(n), - _ => None, - } - }; - const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY; -} - -#[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl<I> SourceIter for Flatten<I> where I: SourceIter + TrustedFused + Iterator, |
