remove separate no-drop code path since it resulted in more LLVM IR
This commit is contained in:
parent
435219dd82
commit
acdd441cc3
1 changed files with 15 additions and 32 deletions
|
@ -2174,10 +2174,12 @@ impl<T> InPlaceDrop<T> {
|
||||||
impl<T> Drop for InPlaceDrop<T> {
|
impl<T> Drop for InPlaceDrop<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
if mem::needs_drop::<T>() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len()));
|
ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SpecFrom<T, IntoIter<T>> for Vec<T> {
|
impl<T> SpecFrom<T, IntoIter<T>> for Vec<T> {
|
||||||
|
@ -2206,26 +2208,14 @@ impl<T> SpecFrom<T, IntoIter<T>> for Vec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_in_place<T>(src_end: *const T) -> impl FnMut(*mut T, T) -> Result<*mut T, !> {
|
|
||||||
move |mut dst, item| {
|
|
||||||
unsafe {
|
|
||||||
// the InPlaceIterable contract cannot be verified precisely here since
|
|
||||||
// try_fold has an exclusive reference to the source pointer
|
|
||||||
// all we can do is check if it's still in range
|
|
||||||
debug_assert!(dst as *const _ <= src_end, "InPlaceIterable contract violation");
|
|
||||||
ptr::write(dst, item);
|
|
||||||
dst = dst.add(1);
|
|
||||||
}
|
|
||||||
Ok(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_in_place_with_drop<T>(
|
fn write_in_place_with_drop<T>(
|
||||||
src_end: *const T,
|
src_end: *const T,
|
||||||
) -> impl FnMut(InPlaceDrop<T>, T) -> Result<InPlaceDrop<T>, !> {
|
) -> impl FnMut(InPlaceDrop<T>, T) -> Result<InPlaceDrop<T>, !> {
|
||||||
move |mut sink, item| {
|
move |mut sink, item| {
|
||||||
unsafe {
|
unsafe {
|
||||||
// same caveat as above
|
// the InPlaceIterable contract cannot be verified precisely here since
|
||||||
|
// try_fold has an exclusive reference to the source pointer
|
||||||
|
// all we can do is check if it's still in range
|
||||||
debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation");
|
debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation");
|
||||||
ptr::write(sink.dst, item);
|
ptr::write(sink.dst, item);
|
||||||
sink.dst = sink.dst.add(1);
|
sink.dst = sink.dst.add(1);
|
||||||
|
@ -2263,23 +2253,16 @@ where
|
||||||
(inner.buf.as_ptr(), inner.buf.as_ptr() as *mut T, inner.end as *const T, inner.cap)
|
(inner.buf.as_ptr(), inner.buf.as_ptr() as *mut T, inner.end as *const T, inner.cap)
|
||||||
};
|
};
|
||||||
|
|
||||||
// use try-fold
|
// use try-fold since
|
||||||
// - it vectorizes better for some iterator adapters
|
// - it vectorizes better for some iterator adapters
|
||||||
// - unlike most internal iteration methods methods it only takes a &mut self
|
// - unlike most internal iteration methods methods it only takes a &mut self
|
||||||
// - lets us thread the write pointer through its innards and get it back in the end
|
// - it lets us thread the write pointer through its innards and get it back in the end
|
||||||
let dst = if mem::needs_drop::<T>() {
|
|
||||||
// special-case drop handling since it forces us to lug that extra field around which
|
|
||||||
// can inhibit optimizations
|
|
||||||
let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf };
|
let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf };
|
||||||
let sink = iterator
|
let sink = iterator
|
||||||
.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end))
|
.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// iteration succeeded, don't drop head
|
// iteration succeeded, don't drop head
|
||||||
let sink = mem::ManuallyDrop::new(sink);
|
let dst = mem::ManuallyDrop::new(sink).dst;
|
||||||
sink.dst
|
|
||||||
} else {
|
|
||||||
iterator.try_fold::<_, _, Result<_, !>>(dst_buf, write_in_place(dst_end)).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let src = unsafe { iterator.as_inner().as_into_iter() };
|
let src = unsafe { iterator.as_inner().as_into_iter() };
|
||||||
// check if SourceIter and InPlaceIterable contracts were upheld.
|
// check if SourceIter and InPlaceIterable contracts were upheld.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue