Skip to content

Commit 6e436be

Browse files
authored
Rollup merge of rust-lang#37709 - bluss:cleaner-vec-extend, r=alexcrichton
vec: Write the .extend() specialization in cleaner style As far as possible, use regular `default fn` specialization in favour of ad-hoc conditionals. No intentional functional change. Code quality was validated against the same benchmarks that were used in initial trusted len development. This change is prompted by taking impressions from rust-lang#27749 (comment)
2 parents 69717bb + 5058e58 commit 6e436be

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

src/libcollections/vec.rs

+41-30
Original file line numberDiff line numberDiff line change
@@ -1586,36 +1586,34 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
15861586
impl<T> Extend<T> for Vec<T> {
15871587
#[inline]
15881588
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1589-
self.extend_desugared(iter.into_iter())
1589+
self.spec_extend(iter.into_iter())
15901590
}
15911591
}
15921592

1593-
trait IsTrustedLen : Iterator {
1594-
fn trusted_len(&self) -> Option<usize> { None }
1593+
trait SpecExtend<I> {
1594+
fn spec_extend(&mut self, iter: I);
15951595
}
1596-
impl<I> IsTrustedLen for I where I: Iterator { }
15971596

1598-
impl<I> IsTrustedLen for I where I: TrustedLen
1597+
impl<I, T> SpecExtend<I> for Vec<T>
1598+
where I: Iterator<Item=T>,
15991599
{
1600-
fn trusted_len(&self) -> Option<usize> {
1601-
let (low, high) = self.size_hint();
1600+
default fn spec_extend(&mut self, iter: I) {
1601+
self.extend_desugared(iter)
1602+
}
1603+
}
1604+
1605+
impl<I, T> SpecExtend<I> for Vec<T>
1606+
where I: TrustedLen<Item=T>,
1607+
{
1608+
fn spec_extend(&mut self, iterator: I) {
1609+
// This is the case for a TrustedLen iterator.
1610+
let (low, high) = iterator.size_hint();
16021611
if let Some(high_value) = high {
16031612
debug_assert_eq!(low, high_value,
16041613
"TrustedLen iterator's size hint is not exact: {:?}",
16051614
(low, high));
16061615
}
1607-
high
1608-
}
1609-
}
1610-
1611-
impl<T> Vec<T> {
1612-
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
1613-
// This function should be the moral equivalent of:
1614-
//
1615-
// for item in iterator {
1616-
// self.push(item);
1617-
// }
1618-
if let Some(additional) = iterator.trusted_len() {
1616+
if let Some(additional) = high {
16191617
self.reserve(additional);
16201618
unsafe {
16211619
let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
@@ -1628,17 +1626,30 @@ impl<T> Vec<T> {
16281626
}
16291627
}
16301628
} else {
1631-
while let Some(element) = iterator.next() {
1632-
let len = self.len();
1633-
if len == self.capacity() {
1634-
let (lower, _) = iterator.size_hint();
1635-
self.reserve(lower.saturating_add(1));
1636-
}
1637-
unsafe {
1638-
ptr::write(self.get_unchecked_mut(len), element);
1639-
// NB can't overflow since we would have had to alloc the address space
1640-
self.set_len(len + 1);
1641-
}
1629+
self.extend_desugared(iterator)
1630+
}
1631+
}
1632+
}
1633+
1634+
impl<T> Vec<T> {
1635+
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
1636+
// This is the case for a general iterator.
1637+
//
1638+
// This function should be the moral equivalent of:
1639+
//
1640+
// for item in iterator {
1641+
// self.push(item);
1642+
// }
1643+
while let Some(element) = iterator.next() {
1644+
let len = self.len();
1645+
if len == self.capacity() {
1646+
let (lower, _) = iterator.size_hint();
1647+
self.reserve(lower.saturating_add(1));
1648+
}
1649+
unsafe {
1650+
ptr::write(self.get_unchecked_mut(len), element);
1651+
// NB can't overflow since we would have had to alloc the address space
1652+
self.set_len(len + 1);
16421653
}
16431654
}
16441655
}

0 commit comments

Comments
 (0)