Skip to content

Commit 5058e58

Browse files
committed
vec: Write the .extend() specialization in cleaner style
As far as possible, use regular `default fn` specialization in favour of ad-hoc conditionals.
1 parent c9f16bb commit 5058e58

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)