Skip to content

Commit 4955711

Browse files
committed
Use TrustedLen for Vec's FromIterator and Extend
1 parent 9ae9930 commit 4955711

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

src/libcollections/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#![feature(specialization)]
5151
#![feature(staged_api)]
5252
#![feature(step_by)]
53+
#![feature(trusted_len)]
5354
#![feature(unicode)]
5455
#![feature(unique)]
5556
#![cfg_attr(test, feature(rand, test))]

src/libcollections/vec.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use core::cmp::Ordering;
6868
use core::fmt;
6969
use core::hash::{self, Hash};
7070
use core::intrinsics::{arith_offset, assume};
71-
use core::iter::{FromIterator, FusedIterator};
71+
use core::iter::{FromIterator, FusedIterator, TrustedLen};
7272
use core::mem;
7373
use core::ops::{Index, IndexMut};
7474
use core::ops;
@@ -1589,23 +1589,49 @@ impl<T> SpecExtend<Vec<T>> for Vec<T> {
15891589
}
15901590
}
15911591

1592+
trait IsTrustedLen : Iterator {
1593+
fn trusted_len(&self) -> Option<usize> { None }
1594+
}
1595+
impl<I> IsTrustedLen for I where I: Iterator { }
1596+
1597+
impl<I> IsTrustedLen for I where I: TrustedLen
1598+
{
1599+
fn trusted_len(&self) -> Option<usize> {
1600+
self.size_hint().1
1601+
}
1602+
}
1603+
15921604
impl<T> Vec<T> {
15931605
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
15941606
// This function should be the moral equivalent of:
15951607
//
15961608
// for item in iterator {
15971609
// self.push(item);
15981610
// }
1599-
while let Some(element) = iterator.next() {
1600-
let len = self.len();
1601-
if len == self.capacity() {
1602-
let (lower, _) = iterator.size_hint();
1603-
self.reserve(lower.saturating_add(1));
1604-
}
1611+
if let Some(additional) = iterator.trusted_len() {
1612+
self.reserve(additional);
16051613
unsafe {
1606-
ptr::write(self.get_unchecked_mut(len), element);
1607-
// NB can't overflow since we would have had to alloc the address space
1608-
self.set_len(len + 1);
1614+
let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
1615+
let mut local_len = SetLenOnDrop::new(&mut self.len);
1616+
for element in iterator {
1617+
ptr::write(ptr, element);
1618+
ptr = ptr.offset(1);
1619+
// NB can't overflow since we would have had to alloc the address space
1620+
local_len.increment_len(1);
1621+
}
1622+
}
1623+
} else {
1624+
while let Some(element) = iterator.next() {
1625+
let len = self.len();
1626+
if len == self.capacity() {
1627+
let (lower, _) = iterator.size_hint();
1628+
self.reserve(lower.saturating_add(1));
1629+
}
1630+
unsafe {
1631+
ptr::write(self.get_unchecked_mut(len), element);
1632+
// NB can't overflow since we would have had to alloc the address space
1633+
self.set_len(len + 1);
1634+
}
16091635
}
16101636
}
16111637
}

0 commit comments

Comments
 (0)