Skip to content

Commit b283881

Browse files
committed
rollup merge of #22394: alexcrichton/vec-from-iter-comment
Requested by Niko in #22200 (and is good to have anyway)
2 parents d8450d6 + 95a28c9 commit b283881

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
@@ -1407,7 +1407,7 @@ impl<T> ops::DerefMut for Vec<T> {
14071407
#[stable(feature = "rust1", since = "1.0.0")]
14081408
impl<T> FromIterator<T> for Vec<T> {
14091409
#[inline]
1410-
fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
1410+
fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
14111411
let (lower, _) = iterator.size_hint();
14121412
let mut vector = Vec::with_capacity(lower);
14131413

@@ -1417,22 +1417,31 @@ impl<T> FromIterator<T> for Vec<T> {
14171417
// vector.push(item);
14181418
// }
14191419
//
1420-
// This equivalent crucially runs the iterator precisely once. The
1421-
// optimization below (eliding bound/growth checks) means that we
1422-
// actually run the iterator twice. To ensure the "moral equivalent" we
1423-
// do a `fuse()` operation to ensure that the iterator continues to
1424-
// return `None` after seeing the first `None`.
1425-
let mut i = iterator.fuse();
1426-
for element in i.by_ref().take(vector.capacity()) {
1420+
// This equivalent crucially runs the iterator precisely once. Below we
1421+
// actually in theory run the iterator twice (one without bounds checks
1422+
// and one with). To achieve the "moral equivalent", we use the `if`
1423+
// statement below to break out early.
1424+
//
1425+
// If the first loop has terminated, then we have one of two conditions.
1426+
//
1427+
// 1. The underlying iterator returned `None`. In this case we are
1428+
// guaranteed that less than `vector.capacity()` elements have been
1429+
// returned, so we break out early.
1430+
// 2. The underlying iterator yielded `vector.capacity()` elements and
1431+
// has not yielded `None` yet. In this case we run the iterator to
1432+
// its end below.
1433+
for element in iterator.by_ref().take(vector.capacity()) {
14271434
let len = vector.len();
14281435
unsafe {
14291436
ptr::write(vector.get_unchecked_mut(len), element);
14301437
vector.set_len(len + 1);
14311438
}
14321439
}
14331440

1434-
for element in i {
1435-
vector.push(element)
1441+
if vector.len() == vector.capacity() {
1442+
for element in iterator {
1443+
vector.push(element);
1444+
}
14361445
}
14371446
vector
14381447
}

0 commit comments

Comments
 (0)