Skip to content

Commit 366afd9

Browse files
committed
move free-standing method into trait impl
1 parent 4220852 commit 366afd9

File tree

1 file changed

+75
-79
lines changed

1 file changed

+75
-79
lines changed

src/liballoc/vec.rs

Lines changed: 75 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,83 +2082,6 @@ impl<T> Drop for InPlaceDrop<T> {
20822082
}
20832083
}
20842084

2085-
fn from_into_iter_source<T, I>(mut iterator: I) -> Vec<T>
2086-
where
2087-
I: Iterator<Item = T> + InPlaceIterable + SourceIter<Source = IntoIter<T>>,
2088-
{
2089-
// This specialization only makes sense if we're juggling real allocations.
2090-
// Additionally some of the pointer arithmetic would panic on ZSTs.
2091-
if mem::size_of::<T>() == 0 {
2092-
return SpecFromNested::from_iter(iterator);
2093-
}
2094-
2095-
let src_buf = iterator.as_inner().buf.as_ptr();
2096-
let src_end = iterator.as_inner().end;
2097-
let dst = src_buf;
2098-
2099-
let dst = if mem::needs_drop::<T>() {
2100-
// special-case drop handling since it prevents vectorization
2101-
let mut sink = InPlaceDrop { inner: src_buf, dst, did_panic: true };
2102-
let _ = iterator.try_for_each::<_, Result<_, !>>(|item| {
2103-
unsafe {
2104-
debug_assert!(
2105-
sink.dst as *const _ <= src_end,
2106-
"InPlaceIterable contract violation"
2107-
);
2108-
ptr::write(sink.dst, item);
2109-
sink.dst = sink.dst.add(1);
2110-
}
2111-
Ok(())
2112-
});
2113-
sink.did_panic = false;
2114-
sink.dst
2115-
} else {
2116-
// use try-fold
2117-
// - it vectorizes better
2118-
// - unlike most internal iteration methods methods it only takes a &mut self
2119-
// - lets us thread the write pointer through its innards and get it back in the end
2120-
iterator
2121-
.try_fold::<_, _, Result<_, !>>(dst, move |mut dst, item| {
2122-
unsafe {
2123-
// the InPlaceIterable contract cannot be verified precisely here since
2124-
// try_fold has an exclusive reference to the source pointer
2125-
// all we can do is check if it's still in range
2126-
debug_assert!(dst as *const _ <= src_end, "InPlaceIterable contract violation");
2127-
ptr::write(dst, item);
2128-
dst = dst.add(1);
2129-
}
2130-
Ok(dst)
2131-
})
2132-
.unwrap()
2133-
};
2134-
2135-
let src = iterator.as_inner();
2136-
// check if SourceIter and InPlaceIterable contracts were upheld.
2137-
// caveat: if they weren't we may not even make it to this point
2138-
debug_assert_eq!(src_buf, src.buf.as_ptr());
2139-
debug_assert!(dst as *const _ <= src.ptr, "InPlaceIterable contract violation");
2140-
2141-
if mem::needs_drop::<T>() {
2142-
// drop tail if iterator was only partially exhaused
2143-
unsafe {
2144-
ptr::drop_in_place(src.as_mut_slice());
2145-
}
2146-
}
2147-
2148-
let vec = unsafe {
2149-
let len = dst.offset_from(src_buf) as usize;
2150-
Vec::from_raw_parts(src.buf.as_ptr(), len, src.cap)
2151-
};
2152-
// prevent drop of the underlying storage by turning the IntoIter into
2153-
// the equivalent of Vec::new().into_iter()
2154-
src.cap = 0;
2155-
src.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
2156-
src.ptr = src.buf.as_ptr();
2157-
src.end = src.buf.as_ptr();
2158-
2159-
vec
2160-
}
2161-
21622085
impl<T> SpecFrom<T, IntoIter<T>> for Vec<T> {
21632086
fn from_iter(iterator: IntoIter<T>) -> Self {
21642087
// A common case is passing a vector into a function which immediately
@@ -2193,8 +2116,81 @@ impl<T, I> SpecFrom<T, I> for Vec<T>
21932116
where
21942117
I: Iterator<Item = T> + InPlaceIterable + SourceIter<Source = IntoIter<T>>,
21952118
{
2196-
default fn from_iter(iterator: I) -> Self {
2197-
from_into_iter_source(iterator)
2119+
default fn from_iter(mut iterator: I) -> Self {
2120+
// This specialization only makes sense if we're juggling real allocations.
2121+
// Additionally some of the pointer arithmetic would panic on ZSTs.
2122+
if mem::size_of::<T>() == 0 {
2123+
return SpecFromNested::from_iter(iterator);
2124+
}
2125+
2126+
let src_buf = iterator.as_inner().buf.as_ptr();
2127+
let src_end = iterator.as_inner().end;
2128+
let dst = src_buf;
2129+
2130+
let dst = if mem::needs_drop::<T>() {
2131+
// special-case drop handling since it prevents vectorization
2132+
let mut sink = InPlaceDrop { inner: src_buf, dst, did_panic: true };
2133+
let _ = iterator.try_for_each::<_, Result<_, !>>(|item| {
2134+
unsafe {
2135+
debug_assert!(
2136+
sink.dst as *const _ <= src_end,
2137+
"InPlaceIterable contract violation"
2138+
);
2139+
ptr::write(sink.dst, item);
2140+
sink.dst = sink.dst.add(1);
2141+
}
2142+
Ok(())
2143+
});
2144+
sink.did_panic = false;
2145+
sink.dst
2146+
} else {
2147+
// use try-fold
2148+
// - it vectorizes better
2149+
// - unlike most internal iteration methods methods it only takes a &mut self
2150+
// - lets us thread the write pointer through its innards and get it back in the end
2151+
iterator
2152+
.try_fold::<_, _, Result<_, !>>(dst, move |mut dst, item| {
2153+
unsafe {
2154+
// the InPlaceIterable contract cannot be verified precisely here since
2155+
// try_fold has an exclusive reference to the source pointer
2156+
// all we can do is check if it's still in range
2157+
debug_assert!(
2158+
dst as *const _ <= src_end,
2159+
"InPlaceIterable contract violation"
2160+
);
2161+
ptr::write(dst, item);
2162+
dst = dst.add(1);
2163+
}
2164+
Ok(dst)
2165+
})
2166+
.unwrap()
2167+
};
2168+
2169+
let src = iterator.as_inner();
2170+
// check if SourceIter and InPlaceIterable contracts were upheld.
2171+
// caveat: if they weren't we may not even make it to this point
2172+
debug_assert_eq!(src_buf, src.buf.as_ptr());
2173+
debug_assert!(dst as *const _ <= src.ptr, "InPlaceIterable contract violation");
2174+
2175+
if mem::needs_drop::<T>() {
2176+
// drop tail if iterator was only partially exhaused
2177+
unsafe {
2178+
ptr::drop_in_place(src.as_mut_slice());
2179+
}
2180+
}
2181+
2182+
let vec = unsafe {
2183+
let len = dst.offset_from(src_buf) as usize;
2184+
Vec::from_raw_parts(src.buf.as_ptr(), len, src.cap)
2185+
};
2186+
// prevent drop of the underlying storage by turning the IntoIter into
2187+
// the equivalent of Vec::new().into_iter()
2188+
src.cap = 0;
2189+
src.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
2190+
src.ptr = src.buf.as_ptr();
2191+
src.end = src.buf.as_ptr();
2192+
2193+
vec
21982194
}
21992195
}
22002196

0 commit comments

Comments
 (0)