about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-11-11 12:54:10 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-11-11 12:54:10 +0100
commit5058e58676bd6c3af63fc4e35a327c07fce2a276 (patch)
tree2aa80020b75639ccb8ed0bc21c9898cf3c426ade
parentc9f16bbc419d1a945823d91419bbb1fc75bfbc79 (diff)
downloadrust-5058e58676bd6c3af63fc4e35a327c07fce2a276.tar.gz
rust-5058e58676bd6c3af63fc4e35a327c07fce2a276.zip
vec: Write the .extend() specialization in cleaner style
As far as possible, use regular `default fn` specialization in favour of
ad-hoc conditionals.
-rw-r--r--src/libcollections/vec.rs71
1 files changed, 41 insertions, 30 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 71c49ee616c..53b7ae0703b 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1586,36 +1586,34 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
 impl<T> Extend<T> for Vec<T> {
     #[inline]
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
-        self.extend_desugared(iter.into_iter())
+        self.spec_extend(iter.into_iter())
     }
 }
 
-trait IsTrustedLen : Iterator {
-    fn trusted_len(&self) -> Option<usize> { None }
+trait SpecExtend<I> {
+    fn spec_extend(&mut self, iter: I);
 }
-impl<I> IsTrustedLen for I where I: Iterator { }
 
-impl<I> IsTrustedLen for I where I: TrustedLen
+impl<I, T> SpecExtend<I> for Vec<T>
+    where I: Iterator<Item=T>,
 {
-    fn trusted_len(&self) -> Option<usize> {
-        let (low, high) = self.size_hint();
+    default fn spec_extend(&mut self, iter: I) {
+        self.extend_desugared(iter)
+    }
+}
+
+impl<I, T> SpecExtend<I> for Vec<T>
+    where I: TrustedLen<Item=T>,
+{
+    fn spec_extend(&mut self, iterator: I) {
+        // This is the case for a TrustedLen iterator.
+        let (low, high) = iterator.size_hint();
         if let Some(high_value) = high {
             debug_assert_eq!(low, high_value,
                              "TrustedLen iterator's size hint is not exact: {:?}",
                              (low, high));
         }
-        high
-    }
-}
-
-impl<T> Vec<T> {
-    fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
-        // This function should be the moral equivalent of:
-        //
-        //      for item in iterator {
-        //          self.push(item);
-        //      }
-        if let Some(additional) = iterator.trusted_len() {
+        if let Some(additional) = high {
             self.reserve(additional);
             unsafe {
                 let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
@@ -1628,17 +1626,30 @@ impl<T> Vec<T> {
                 }
             }
         } else {
-            while let Some(element) = iterator.next() {
-                let len = self.len();
-                if len == self.capacity() {
-                    let (lower, _) = iterator.size_hint();
-                    self.reserve(lower.saturating_add(1));
-                }
-                unsafe {
-                    ptr::write(self.get_unchecked_mut(len), element);
-                    // NB can't overflow since we would have had to alloc the address space
-                    self.set_len(len + 1);
-                }
+            self.extend_desugared(iterator)
+        }
+    }
+}
+
+impl<T> Vec<T> {
+    fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
+        // This is the case for a general iterator.
+        //
+        // This function should be the moral equivalent of:
+        //
+        //      for item in iterator {
+        //          self.push(item);
+        //      }
+        while let Some(element) = iterator.next() {
+            let len = self.len();
+            if len == self.capacity() {
+                let (lower, _) = iterator.size_hint();
+                self.reserve(lower.saturating_add(1));
+            }
+            unsafe {
+                ptr::write(self.get_unchecked_mut(len), element);
+                // NB can't overflow since we would have had to alloc the address space
+                self.set_len(len + 1);
             }
         }
     }