Skip to content

Commit a7b5d69

Browse files
committed
Auto merge of #32851 - apasel422:spec-extend, r=alexcrichton
Specialize `Extend` to `append` for `{LinkedList, Vec}`
2 parents 4091cd0 + cf37af1 commit a7b5d69

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

src/libcollections/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,10 @@ pub enum Bound<T> {
132132
/// An infinite endpoint. Indicates that there is no bound in this direction.
133133
Unbounded,
134134
}
135+
136+
/// An intermediate trait for specialization of `Extend`.
137+
#[doc(hidden)]
138+
trait SpecExtend<I: IntoIterator> {
139+
/// Extends `self` with the contents of the given iterator.
140+
fn spec_extend(&mut self, iter: I);
141+
}

src/libcollections/linked_list.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use core::mem;
3030
use core::ops::{BoxPlace, InPlace, Place, Placer};
3131
use core::ptr::{self, Shared};
3232

33+
use super::SpecExtend;
34+
3335
/// A doubly-linked list.
3436
#[stable(feature = "rust1", since = "1.0.0")]
3537
pub struct LinkedList<T> {
@@ -969,12 +971,24 @@ impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
969971
#[stable(feature = "rust1", since = "1.0.0")]
970972
impl<A> Extend<A> for LinkedList<A> {
971973
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
974+
<Self as SpecExtend<T>>::spec_extend(self, iter);
975+
}
976+
}
977+
978+
impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> {
979+
default fn spec_extend(&mut self, iter: I) {
972980
for elt in iter {
973981
self.push_back(elt);
974982
}
975983
}
976984
}
977985

986+
impl<T> SpecExtend<LinkedList<T>> for LinkedList<T> {
987+
fn spec_extend(&mut self, ref mut other: LinkedList<T>) {
988+
self.append(other);
989+
}
990+
}
991+
978992
#[stable(feature = "extend_ref", since = "1.2.0")]
979993
impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> {
980994
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {

src/libcollections/vec.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ use core::ops;
7575
use core::ptr;
7676
use core::slice;
7777

78+
use super::SpecExtend;
7879
use super::range::RangeArgument;
7980

8081
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector.'
@@ -1390,10 +1391,22 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
13901391
impl<T> Extend<T> for Vec<T> {
13911392
#[inline]
13921393
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1394+
<Self as SpecExtend<I>>::spec_extend(self, iter);
1395+
}
1396+
}
1397+
1398+
impl<I: IntoIterator> SpecExtend<I> for Vec<I::Item> {
1399+
default fn spec_extend(&mut self, iter: I) {
13931400
self.extend_desugared(iter.into_iter())
13941401
}
13951402
}
13961403

1404+
impl<T> SpecExtend<Vec<T>> for Vec<T> {
1405+
fn spec_extend(&mut self, ref mut other: Vec<T>) {
1406+
self.append(other);
1407+
}
1408+
}
1409+
13971410
impl<T> Vec<T> {
13981411
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
13991412
// This function should be the moral equivalent of:

src/libcollectionstest/linked_list.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,22 @@ fn test_extend_ref() {
339339
assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6]));
340340
}
341341

342+
#[test]
343+
fn test_extend() {
344+
let mut a = LinkedList::new();
345+
a.push_back(1);
346+
a.extend(vec![2, 3, 4]); // uses iterator
347+
348+
assert_eq!(a.len(), 4);
349+
assert!(a.iter().eq(&[1, 2, 3, 4]));
350+
351+
let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect();
352+
a.extend(b); // specializes to `append`
353+
354+
assert_eq!(a.len(), 7);
355+
assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
356+
}
357+
342358
#[bench]
343359
fn bench_collect_into(b: &mut test::Bencher) {
344360
let v = &[0; 64];

src/libcollectionstest/vec.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ fn test_extend() {
9393
for i in 3..10 { w.push(i) }
9494

9595
assert_eq!(v, w);
96+
97+
v.extend(w.clone()); // specializes to `append`
98+
assert!(v.iter().eq(w.iter().chain(w.iter())));
9699
}
97100

98101
#[test]

0 commit comments

Comments
 (0)