Specialize Extend to append for {LinkedList, Vec}

This commit is contained in:
Andrew Paseltiner 2016-04-08 23:36:54 -04:00
parent 7e99694378
commit cf37af1627
No known key found for this signature in database
GPG Key ID: DA5CDC15F9BEDB2B
5 changed files with 53 additions and 0 deletions

View File

@ -133,3 +133,10 @@ pub enum Bound<T> {
/// An infinite endpoint. Indicates that there is no bound in this direction.
Unbounded,
}
/// An intermediate trait for specialization of `Extend`.
#[doc(hidden)]
trait SpecExtend<I: IntoIterator> {
/// Extends `self` with the contents of the given iterator.
fn spec_extend(&mut self, iter: I);
}

View File

@ -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<T> {
@ -969,12 +971,24 @@ impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> Extend<A> for LinkedList<A> {
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
<Self as SpecExtend<T>>::spec_extend(self, iter);
}
}
impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> {
default fn spec_extend(&mut self, iter: I) {
for elt in iter {
self.push_back(elt);
}
}
}
impl<T> SpecExtend<LinkedList<T>> for LinkedList<T> {
fn spec_extend(&mut self, ref mut other: LinkedList<T>) {
self.append(other);
}
}
#[stable(feature = "extend_ref", since = "1.2.0")]
impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {

View File

@ -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<T>` but pronounced 'vector.'
@ -1390,10 +1391,22 @@ 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 as SpecExtend<I>>::spec_extend(self, iter);
}
}
impl<I: IntoIterator> SpecExtend<I> for Vec<I::Item> {
default fn spec_extend(&mut self, iter: I) {
self.extend_desugared(iter.into_iter())
}
}
impl<T> SpecExtend<Vec<T>> for Vec<T> {
fn spec_extend(&mut self, ref mut other: Vec<T>) {
self.append(other);
}
}
impl<T> Vec<T> {
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
// This function should be the moral equivalent of:

View File

@ -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];

View File

@ -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]