Skip to content

Commit 439f630

Browse files
committed
support in-place collecting additional FlatMap shapes
1 parent 7047fb4 commit 439f630

File tree

2 files changed

+70
-15
lines changed

2 files changed

+70
-15
lines changed

library/alloc/tests/vec.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,17 @@ fn test_in_place_specialization_step_up_down() {
12121212
let sink_bytes = sink.capacity() * 4;
12131213
assert_ne!(src_bytes, sink_bytes);
12141214
assert_eq!(sink.len(), 2);
1215+
1216+
let src = vec![[0u8; 4]; 256];
1217+
let srcptr = src.as_ptr();
1218+
let iter = src
1219+
.into_iter()
1220+
.flat_map(|a| {
1221+
a.into_iter().map(|b| b.wrapping_add(1))
1222+
});
1223+
assert_in_place_trait(&iter);
1224+
let sink = iter.collect::<Vec<_>>();
1225+
assert_eq!(srcptr as *const u8, sink.as_ptr());
12151226
}
12161227

12171228
#[test]

library/core/src/iter/adapters/flatten.rs

+59-15
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use crate::iter::adapters::SourceIter;
22
use crate::iter::{
3-
DoubleEndedIterator, Fuse, FusedIterator, InPlaceIterable, Iterator, Map, TrustedFused,
4-
TrustedLen,
3+
Cloned, Copied, DoubleEndedIterator, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable,
4+
Iterator, Map, TrustedFused, TrustedLen,
55
};
6+
use crate::iter::{Once, OnceWith};
67
use crate::num::NonZeroUsize;
78
use crate::ops::{ControlFlow, Try};
8-
use crate::{fmt, option};
9-
use core::iter::Once;
9+
use crate::result;
10+
use crate::{array, fmt, option};
1011

1112
/// An iterator that maps each element to an iterator, and yields the elements
1213
/// of the produced iterators.
@@ -154,10 +155,10 @@ where
154155
unsafe impl<I, U, F> InPlaceIterable for FlatMap<I, U, F>
155156
where
156157
I: InPlaceIterable,
157-
U: KnownExpansionFactor + IntoIterator,
158+
U: BoundedSize + IntoIterator,
158159
{
159160
const EXPAND_BY: Option<NonZeroUsize> = const {
160-
match (I::EXPAND_BY, U::FACTOR) {
161+
match (I::EXPAND_BY, U::UPPER_BOUND) {
161162
(Some(m), Some(n)) => m.checked_mul(n),
162163
_ => None,
163164
}
@@ -180,16 +181,59 @@ where
180181
}
181182
}
182183

184+
/// Marker trait for iterators/iterables which have a statically known upper
185+
/// bound of the number of items they can produce.
186+
///
187+
/// # Safety
188+
///
189+
/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`.
190+
/// Used in specializations. Implementations must not be conditional on lifetimes or
191+
/// user-implementable traits.
183192
#[rustc_specialization_trait]
184-
trait KnownExpansionFactor {
185-
const FACTOR: Option<NonZeroUsize> = NonZeroUsize::new(1);
193+
#[unstable(issue = "none", feature = "inplace_iteration")]
194+
unsafe trait BoundedSize {
195+
const UPPER_BOUND: Option<NonZeroUsize> = NonZeroUsize::new(1);
186196
}
187197

188-
impl<T> KnownExpansionFactor for Option<T> {}
189-
impl<T> KnownExpansionFactor for option::IntoIter<T> {}
190-
impl<T> KnownExpansionFactor for Once<T> {}
191-
impl<T, const N: usize> KnownExpansionFactor for [T; N] {
192-
const FACTOR: Option<NonZeroUsize> = NonZeroUsize::new(N);
198+
#[unstable(issue = "none", feature = "inplace_iteration")]
199+
unsafe impl<T> BoundedSize for Option<T> {}
200+
#[unstable(issue = "none", feature = "inplace_iteration")]
201+
unsafe impl<T> BoundedSize for option::IntoIter<T> {}
202+
#[unstable(issue = "none", feature = "inplace_iteration")]
203+
unsafe impl<T, U> BoundedSize for Result<T, U> {}
204+
#[unstable(issue = "none", feature = "inplace_iteration")]
205+
unsafe impl<T> BoundedSize for result::IntoIter<T> {}
206+
#[unstable(issue = "none", feature = "inplace_iteration")]
207+
unsafe impl<T> BoundedSize for Once<T> {}
208+
#[unstable(issue = "none", feature = "inplace_iteration")]
209+
unsafe impl<T> BoundedSize for OnceWith<T> {}
210+
#[unstable(issue = "none", feature = "inplace_iteration")]
211+
unsafe impl<T, const N: usize> BoundedSize for [T; N] {
212+
const UPPER_BOUND: Option<NonZeroUsize> = NonZeroUsize::new(N);
213+
}
214+
#[unstable(issue = "none", feature = "inplace_iteration")]
215+
unsafe impl<T, const N: usize> BoundedSize for array::IntoIter<T, N> {
216+
const UPPER_BOUND: Option<NonZeroUsize> = NonZeroUsize::new(N);
217+
}
218+
#[unstable(issue = "none", feature = "inplace_iteration")]
219+
unsafe impl<I: BoundedSize, P> BoundedSize for Filter<I, P> {
220+
const UPPER_BOUND: Option<NonZeroUsize> = I::UPPER_BOUND;
221+
}
222+
#[unstable(issue = "none", feature = "inplace_iteration")]
223+
unsafe impl<I: BoundedSize, P> BoundedSize for FilterMap<I, P> {
224+
const UPPER_BOUND: Option<NonZeroUsize> = I::UPPER_BOUND;
225+
}
226+
#[unstable(issue = "none", feature = "inplace_iteration")]
227+
unsafe impl<I: BoundedSize, F> BoundedSize for Map<I, F> {
228+
const UPPER_BOUND: Option<NonZeroUsize> = I::UPPER_BOUND;
229+
}
230+
#[unstable(issue = "none", feature = "inplace_iteration")]
231+
unsafe impl<I: BoundedSize> BoundedSize for Copied<I> {
232+
const UPPER_BOUND: Option<NonZeroUsize> = I::UPPER_BOUND;
233+
}
234+
#[unstable(issue = "none", feature = "inplace_iteration")]
235+
unsafe impl<I: BoundedSize> BoundedSize for Cloned<I> {
236+
const UPPER_BOUND: Option<NonZeroUsize> = I::UPPER_BOUND;
193237
}
194238

195239
/// An iterator that flattens one level of nesting in an iterator of things
@@ -340,10 +384,10 @@ where
340384
unsafe impl<I> InPlaceIterable for Flatten<I>
341385
where
342386
I: InPlaceIterable + Iterator,
343-
<I as Iterator>::Item: IntoIterator + KnownExpansionFactor,
387+
<I as Iterator>::Item: IntoIterator + BoundedSize,
344388
{
345389
const EXPAND_BY: Option<NonZeroUsize> = const {
346-
match (I::EXPAND_BY, I::Item::FACTOR) {
390+
match (I::EXPAND_BY, I::Item::UPPER_BOUND) {
347391
(Some(m), Some(n)) => m.checked_mul(n),
348392
_ => None,
349393
}

0 commit comments

Comments
 (0)