about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-13 04:21:22 +0100
committerGitHub <noreply@github.com>2019-12-13 04:21:22 +0100
commit2ca7b7e539b429141028953328ea31db77dbf71a (patch)
treebe8404e896662fb1f69be29d53f85f933eb43e72 /src
parent3eeb8d4f2fbae0bb1c587d00b5abeaf938da47f4 (diff)
parent164d1a205d21e0bc54b60cb4e9badf27b3883ffd (diff)
downloadrust-2ca7b7e539b429141028953328ea31db77dbf71a.tar.gz
rust-2ca7b7e539b429141028953328ea31db77dbf71a.zip
Rollup merge of #66341 - crgl:vec-deque-extend, r=Amanieu
Match `VecDeque::extend` to `Vec::extend_desugared`

Currently, `VecDeque::extend` [does not reserve at all](https://github.com/rust-lang/rust/pull/65069#discussion_r333166522). This implementation still runs a check every iteration of the loop, but should reallocate at most once for the common cases where the `size_hint` lower bound is exact. Further optimizations in the future could improve this for some common cases, but given the complexity of the `Vec::extend` implementation it's not immediately clear that this would be worthwhile.
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/collections/vec_deque.rs17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 7795083e058..ebd3f010077 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -2809,7 +2809,22 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Extend<A> for VecDeque<A> {
     fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
-        iter.into_iter().for_each(move |elt| self.push_back(elt));
+        // This function should be the moral equivalent of:
+        //
+        //      for item in iter.into_iter() {
+        //          self.push_back(item);
+        //      }
+        let mut iter = iter.into_iter();
+        while let Some(element) = iter.next() {
+            if self.len() == self.capacity() {
+                let (lower, _) = iter.size_hint();
+                self.reserve(lower.saturating_add(1));
+            }
+
+            let head = self.head;
+            self.head = self.wrap_add(self.head, 1);
+            unsafe { self.buffer_write(head, element); }
+        }
     }
 }