Skip to content

Commit 95a28c9

Browse files
committed
std: Add Vec::from_iter comment
Requested by Niko in #22200 (and is good to have anyway)
1 parent f1bb6c2 commit 95a28c9

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

src/libcollections/vec.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ impl<T> ops::DerefMut for Vec<T> {
13831383
#[stable(feature = "rust1", since = "1.0.0")]
13841384
impl<T> FromIterator<T> for Vec<T> {
13851385
#[inline]
1386-
fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
1386+
fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
13871387
let (lower, _) = iterator.size_hint();
13881388
let mut vector = Vec::with_capacity(lower);
13891389

@@ -1393,22 +1393,31 @@ impl<T> FromIterator<T> for Vec<T> {
13931393
// vector.push(item);
13941394
// }
13951395
//
1396-
// This equivalent crucially runs the iterator precisely once. The
1397-
// optimization below (eliding bound/growth checks) means that we
1398-
// actually run the iterator twice. To ensure the "moral equivalent" we
1399-
// do a `fuse()` operation to ensure that the iterator continues to
1400-
// return `None` after seeing the first `None`.
1401-
let mut i = iterator.fuse();
1402-
for element in i.by_ref().take(vector.capacity()) {
1396+
// This equivalent crucially runs the iterator precisely once. Below we
1397+
// actually in theory run the iterator twice (one without bounds checks
1398+
// and one with). To achieve the "moral equivalent", we use the `if`
1399+
// statement below to break out early.
1400+
//
1401+
// If the first loop has terminated, then we have one of two conditions.
1402+
//
1403+
// 1. The underlying iterator returned `None`. In this case we are
1404+
// guaranteed that less than `vector.capacity()` elements have been
1405+
// returned, so we break out early.
1406+
// 2. The underlying iterator yielded `vector.capacity()` elements and
1407+
// has not yielded `None` yet. In this case we run the iterator to
1408+
// its end below.
1409+
for element in iterator.by_ref().take(vector.capacity()) {
14031410
let len = vector.len();
14041411
unsafe {
14051412
ptr::write(vector.get_unchecked_mut(len), element);
14061413
vector.set_len(len + 1);
14071414
}
14081415
}
14091416

1410-
for element in i {
1411-
vector.push(element)
1417+
if vector.len() == vector.capacity() {
1418+
for element in iterator {
1419+
vector.push(element);
1420+
}
14121421
}
14131422
vector
14141423
}

0 commit comments

Comments
 (0)