From cf37af162721f897e6b3565ab368906621955d90 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 8 Apr 2016 23:36:54 -0400 Subject: [PATCH] Specialize `Extend` to `append` for `{LinkedList, Vec}` --- src/libcollections/lib.rs | 7 +++++++ src/libcollections/linked_list.rs | 14 ++++++++++++++ src/libcollections/vec.rs | 13 +++++++++++++ src/libcollectionstest/linked_list.rs | 16 ++++++++++++++++ src/libcollectionstest/vec.rs | 3 +++ 5 files changed, 53 insertions(+) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 8e62b389a6e3f..05e87b2bb5e52 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -133,3 +133,10 @@ pub enum Bound { /// An infinite endpoint. Indicates that there is no bound in this direction. Unbounded, } + +/// An intermediate trait for specialization of `Extend`. +#[doc(hidden)] +trait SpecExtend { + /// Extends `self` with the contents of the given iterator. + fn spec_extend(&mut self, iter: I); +} diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 85a4fa82e2a34..c974be54bd07d 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -30,6 +30,8 @@ use core::mem; use core::ops::{BoxPlace, InPlace, Place, Placer}; use core::ptr::{self, Shared}; +use super::SpecExtend; + /// A doubly-linked list. #[stable(feature = "rust1", since = "1.0.0")] pub struct LinkedList { @@ -969,12 +971,24 @@ impl<'a, T> IntoIterator for &'a mut LinkedList { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for LinkedList { fn extend>(&mut self, iter: T) { + >::spec_extend(self, iter); + } +} + +impl SpecExtend for LinkedList { + default fn spec_extend(&mut self, iter: I) { for elt in iter { self.push_back(elt); } } } +impl SpecExtend> for LinkedList { + fn spec_extend(&mut self, ref mut other: LinkedList) { + self.append(other); + } +} + #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { fn extend>(&mut self, iter: I) { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index dde5cbb508e1b..58d4a4ed4eb08 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -75,6 +75,7 @@ use core::ops; use core::ptr; use core::slice; +use super::SpecExtend; use super::range::RangeArgument; /// A contiguous growable array type, written `Vec` but pronounced 'vector.' @@ -1390,10 +1391,22 @@ impl<'a, T> IntoIterator for &'a mut Vec { impl Extend for Vec { #[inline] fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter); + } +} + +impl SpecExtend for Vec { + default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter.into_iter()) } } +impl SpecExtend> for Vec { + fn spec_extend(&mut self, ref mut other: Vec) { + self.append(other); + } +} + impl Vec { fn extend_desugared>(&mut self, mut iterator: I) { // This function should be the moral equivalent of: diff --git a/src/libcollectionstest/linked_list.rs b/src/libcollectionstest/linked_list.rs index 7dac967d8030c..3ad4790d36a67 100644 --- a/src/libcollectionstest/linked_list.rs +++ b/src/libcollectionstest/linked_list.rs @@ -339,6 +339,22 @@ fn test_extend_ref() { assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6])); } +#[test] +fn test_extend() { + let mut a = LinkedList::new(); + a.push_back(1); + a.extend(vec![2, 3, 4]); // uses iterator + + assert_eq!(a.len(), 4); + assert!(a.iter().eq(&[1, 2, 3, 4])); + + let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect(); + a.extend(b); // specializes to `append` + + assert_eq!(a.len(), 7); + assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7])); +} + #[bench] fn bench_collect_into(b: &mut test::Bencher) { let v = &[0; 64]; diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index ccdbf1092ff1e..0fb00543ddd97 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -93,6 +93,9 @@ fn test_extend() { for i in 3..10 { w.push(i) } assert_eq!(v, w); + + v.extend(w.clone()); // specializes to `append` + assert!(v.iter().eq(w.iter().chain(w.iter()))); } #[test]