mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 20:28:33 +00:00
Extract the logic for TrustedLen
to a named method that can be called directly
This commit is contained in:
parent
341d8b8a2c
commit
1c966e7f15
@ -2870,6 +2870,41 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// specific extend for `TrustedLen` iterators, called both by the specializations
|
||||||
|
// and internal places where resolving specialization makes compilation slower
|
||||||
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
fn extend_trusted(&mut self, iterator: impl iter::TrustedLen<Item = T>) {
|
||||||
|
let (low, high) = iterator.size_hint();
|
||||||
|
if let Some(additional) = high {
|
||||||
|
debug_assert_eq!(
|
||||||
|
low,
|
||||||
|
additional,
|
||||||
|
"TrustedLen iterator's size hint is not exact: {:?}",
|
||||||
|
(low, high)
|
||||||
|
);
|
||||||
|
self.reserve(additional);
|
||||||
|
unsafe {
|
||||||
|
let mut ptr = self.as_mut_ptr().add(self.len());
|
||||||
|
let mut local_len = SetLenOnDrop::new(&mut self.len);
|
||||||
|
iterator.for_each(move |element| {
|
||||||
|
ptr::write(ptr, element);
|
||||||
|
ptr = ptr.add(1);
|
||||||
|
// Since the loop executes user code which can panic we have to bump the pointer
|
||||||
|
// after each step.
|
||||||
|
// NB can't overflow since we would have had to alloc the address space
|
||||||
|
local_len.increment_len(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Per TrustedLen contract a `None` upper bound means that the iterator length
|
||||||
|
// truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway.
|
||||||
|
// Since the other branch already panics eagerly (via `reserve()`) we do the same here.
|
||||||
|
// This avoids additional codegen for a fallback code path which would eventually
|
||||||
|
// panic anyway.
|
||||||
|
panic!("capacity overflow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a splicing iterator that replaces the specified range in the vector
|
/// Creates a splicing iterator that replaces the specified range in the vector
|
||||||
/// with the given `replace_with` iterator and yields the removed items.
|
/// with the given `replace_with` iterator and yields the removed items.
|
||||||
/// `replace_with` does not need to be the same length as `range`.
|
/// `replace_with` does not need to be the same length as `range`.
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use crate::alloc::Allocator;
|
use crate::alloc::Allocator;
|
||||||
use core::iter::TrustedLen;
|
use core::iter::TrustedLen;
|
||||||
use core::ptr::{self};
|
|
||||||
use core::slice::{self};
|
use core::slice::{self};
|
||||||
|
|
||||||
use super::{IntoIter, SetLenOnDrop, Vec};
|
use super::{IntoIter, Vec};
|
||||||
|
|
||||||
// Specialization trait used for Vec::extend
|
// Specialization trait used for Vec::extend
|
||||||
pub(super) trait SpecExtend<T, I> {
|
pub(super) trait SpecExtend<T, I> {
|
||||||
@ -24,36 +23,7 @@ where
|
|||||||
I: TrustedLen<Item = T>,
|
I: TrustedLen<Item = T>,
|
||||||
{
|
{
|
||||||
default fn spec_extend(&mut self, iterator: I) {
|
default fn spec_extend(&mut self, iterator: I) {
|
||||||
// This is the case for a TrustedLen iterator.
|
self.extend_trusted(iterator)
|
||||||
let (low, high) = iterator.size_hint();
|
|
||||||
if let Some(additional) = high {
|
|
||||||
debug_assert_eq!(
|
|
||||||
low,
|
|
||||||
additional,
|
|
||||||
"TrustedLen iterator's size hint is not exact: {:?}",
|
|
||||||
(low, high)
|
|
||||||
);
|
|
||||||
self.reserve(additional);
|
|
||||||
unsafe {
|
|
||||||
let mut ptr = self.as_mut_ptr().add(self.len());
|
|
||||||
let mut local_len = SetLenOnDrop::new(&mut self.len);
|
|
||||||
iterator.for_each(move |element| {
|
|
||||||
ptr::write(ptr, element);
|
|
||||||
ptr = ptr.add(1);
|
|
||||||
// Since the loop executes user code which can panic we have to bump the pointer
|
|
||||||
// after each step.
|
|
||||||
// NB can't overflow since we would have had to alloc the address space
|
|
||||||
local_len.increment_len(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Per TrustedLen contract a `None` upper bound means that the iterator length
|
|
||||||
// truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway.
|
|
||||||
// Since the other branch already panics eagerly (via `reserve()`) we do the same here.
|
|
||||||
// This avoids additional codegen for a fallback code path which would eventually
|
|
||||||
// panic anyway.
|
|
||||||
panic!("capacity overflow");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user