Skip to content

Commit f0edc2d

Browse files
committed
optimize FromIterator for boxed slice with TrustedLen iterators
1 parent 44a500c commit f0edc2d

File tree

1 file changed

+44
-4
lines changed

1 file changed

+44
-4
lines changed

library/alloc/src/boxed.rs

+44-4
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ use core::fmt;
156156
use core::future::Future;
157157
use core::hash::{Hash, Hasher};
158158
#[cfg(not(no_global_oom_handling))]
159-
use core::iter::FromIterator;
159+
use core::iter::{FromIterator, TrustedLen};
160160
use core::iter::{FusedIterator, Iterator};
161161
use core::marker::Tuple;
162162
use core::marker::{Destruct, Unpin, Unsize};
@@ -2009,11 +2009,51 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> fo
20092009
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
20102010
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T, Global> {}
20112011

2012+
#[cfg(not(no_global_oom_handling))]
2013+
trait SpecFromIter<T, I> {
2014+
fn from_iter(iter: I) -> Self;
2015+
}
2016+
2017+
#[cfg(not(no_global_oom_handling))]
2018+
impl<T, I> SpecFromIter<T, I> for Box<[T]>
2019+
where
2020+
I: Iterator<Item = T>,
2021+
{
2022+
default fn from_iter(iter: I) -> Self {
2023+
iter.collect::<Vec<_>>().into_boxed_slice()
2024+
}
2025+
}
2026+
2027+
#[cfg(not(no_global_oom_handling))]
2028+
impl<T, I> SpecFromIter<T, I> for Box<[T]>
2029+
where
2030+
I: TrustedLen<Item = T>,
2031+
{
2032+
fn from_iter(iter: I) -> Self {
2033+
match iter.size_hint() {
2034+
(low, Some(high)) if low == high => {
2035+
let mut result = Box::new_uninit_slice(high);
2036+
let ptr: *mut T = mem::MaybeUninit::slice_as_mut_ptr(&mut *result);
2037+
for (offset, elem) in iter.enumerate() {
2038+
// Safety: TrustedLen guarantees that offset is in bounds
2039+
unsafe { ptr.add(offset).write(elem) }
2040+
}
2041+
// Safety: TrustedLen guarantees that we initialized all the elements
2042+
unsafe { result.assume_init() }
2043+
}
2044+
_ => panic!(
2045+
".size_hint() provided by TrustedLen iterator is not exact: {:?}",
2046+
iter.size_hint()
2047+
),
2048+
}
2049+
}
2050+
}
2051+
20122052
#[cfg(not(no_global_oom_handling))]
20132053
#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
2014-
impl<I> FromIterator<I> for Box<[I]> {
2015-
fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
2016-
iter.into_iter().collect::<Vec<_>>().into_boxed_slice()
2054+
impl<T> FromIterator<T> for Box<[T]> {
2055+
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2056+
SpecFromIter::from_iter(iter.into_iter())
20172057
}
20182058
}
20192059

0 commit comments

Comments
 (0)