]> git.lizzy.rs Git - rust.git/commitdiff
vec: Write the .extend() specialization in cleaner style
authorUlrik Sverdrup <bluss@users.noreply.github.com>
Fri, 11 Nov 2016 11:54:10 +0000 (12:54 +0100)
committerUlrik Sverdrup <bluss@users.noreply.github.com>
Fri, 11 Nov 2016 11:54:10 +0000 (12:54 +0100)
As far as possible, use regular `default fn` specialization in favour of
ad-hoc conditionals.

src/libcollections/vec.rs

index 71c49ee616cbced754c823e495b7b31aaea477e0..53b7ae0703bf4819e29f50a11ca3bbce6c7f99eb 100644 (file)
@@ -1586,36 +1586,34 @@ fn into_iter(mut self) -> slice::IterMut<'a, 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 @@ fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
                 }
             }
         } 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);
             }
         }
     }