about summary refs log tree commit diff
path: root/src/libcollections/vec.rs
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2015-02-18 23:50:21 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2015-02-18 23:50:21 +1100
commitdfc5c0f1e8799f47f9033bdcc8a7cd8a217620a5 (patch)
treee9c32f2e58b3462a23dd9c472d2f236640b78811 /src/libcollections/vec.rs
parent6c065fc8cb036785f61ff03e05c1563cbb2dd081 (diff)
parent47f91a9484eceef10536d4caac6ef578cd254567 (diff)
Manual merge of #22475 - alexcrichton:rollup, r=alexcrichton
 One windows bot failed spuriously.
Diffstat (limited to 'src/libcollections/vec.rs')
-rw-r--r--src/libcollections/vec.rs89
1 files changed, 46 insertions, 43 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index f294dd3c3e0..bde733644b5 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1252,6 +1252,30 @@ unsafe fn dealloc<T>(ptr: *mut T, len: usize) {
     }
 }
 
+#[doc(hidden)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
+    unsafe {
+        let mut v = Vec::with_capacity(n);
+        let mut ptr = v.as_mut_ptr();
+
+        // Write all elements except the last one
+        for i in 1..n {
+            ptr::write(ptr, Clone::clone(&elem));
+            ptr = ptr.offset(1);
+            v.set_len(i); // Increment the length in every step in case Clone::clone() panics
+        }
+
+        if n > 0 {
+            // We can write the last element directly without cloning needlessly
+            ptr::write(ptr, elem);
+            v.set_len(n);
+        }
+
+        v
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Common trait implementations for Vec
 ////////////////////////////////////////////////////////////////////////////////
@@ -1383,7 +1407,7 @@ impl<T> ops::DerefMut for Vec<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> FromIterator<T> for Vec<T> {
     #[inline]
-    fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
+    fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
         let (lower, _) = iterator.size_hint();
         let mut vector = Vec::with_capacity(lower);
 
@@ -1393,13 +1417,20 @@ impl<T> FromIterator<T> for Vec<T> {
         //          vector.push(item);
         //      }
         //
-        // This equivalent crucially runs the iterator precisely once. The
-        // optimization below (eliding bound/growth checks) means that we
-        // actually run the iterator twice. To ensure the "moral equivalent" we
-        // do a `fuse()` operation to ensure that the iterator continues to
-        // return `None` after seeing the first `None`.
-        let mut i = iterator.fuse();
-        for element in i.by_ref().take(vector.capacity()) {
+        // This equivalent crucially runs the iterator precisely once. Below we
+        // actually in theory run the iterator twice (one without bounds checks
+        // and one with). To achieve the "moral equivalent", we use the `if`
+        // statement below to break out early.
+        //
+        // If the first loop has terminated, then we have one of two conditions.
+        //
+        // 1. The underlying iterator returned `None`. In this case we are
+        //    guaranteed that less than `vector.capacity()` elements have been
+        //    returned, so we break out early.
+        // 2. The underlying iterator yielded `vector.capacity()` elements and
+        //    has not yielded `None` yet. In this case we run the iterator to
+        //    its end below.
+        for element in iterator.by_ref().take(vector.capacity()) {
             let len = vector.len();
             unsafe {
                 ptr::write(vector.get_unchecked_mut(len), element);
@@ -1407,24 +1438,16 @@ impl<T> FromIterator<T> for Vec<T> {
             }
         }
 
-        for element in i {
-            vector.push(element)
+        if vector.len() == vector.capacity() {
+            for element in iterator {
+                vector.push(element);
+            }
         }
         vector
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for Vec<T> {
-    type IntoIter = IntoIter<T>;
-
-    fn into_iter(self) -> IntoIter<T> {
-        self.into_iter()
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> IntoIterator for Vec<T> {
     type Item = T;
     type IntoIter = IntoIter<T>;
@@ -1434,17 +1457,7 @@ impl<T> IntoIterator for Vec<T> {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a Vec<T> {
-    type IntoIter = slice::Iter<'a, T>;
-
-    fn into_iter(self) -> slice::Iter<'a, T> {
-        self.iter()
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> IntoIterator for &'a Vec<T> {
     type Item = &'a T;
     type IntoIter = slice::Iter<'a, T>;
@@ -1454,17 +1467,7 @@ impl<'a, T> IntoIterator for &'a Vec<T> {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a mut Vec<T> {
-    type IntoIter = slice::IterMut<'a, T>;
-
-    fn into_iter(mut self) -> slice::IterMut<'a, T> {
-        self.iter_mut()
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> IntoIterator for &'a mut Vec<T> {
     type Item = &'a mut T;
     type IntoIter = slice::IterMut<'a, T>;