Skip to content

Commit 0b58a2a

Browse files
authored
Rollup merge of rust-lang#72162 - cuviper:extend_one, r=Mark-Simulacrum
Add Extend::{extend_one,extend_reserve} This adds new optional methods on `Extend`: `extend_one` add a single element to the collection, and `extend_reserve` pre-allocates space for the predicted number of incoming elements. These are used in `Iterator` for `partition` and `unzip` as they shuffle elements one-at-a-time into their respective collections.
2 parents 664fcd3 + 02226e0 commit 0b58a2a

File tree

21 files changed

+252
-5
lines changed

21 files changed

+252
-5
lines changed

src/liballoc/collections/binary_heap.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,16 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> {
13761376
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
13771377
<Self as SpecExtend<I>>::spec_extend(self, iter);
13781378
}
1379+
1380+
#[inline]
1381+
fn extend_one(&mut self, item: T) {
1382+
self.push(item);
1383+
}
1384+
1385+
#[inline]
1386+
fn extend_reserve(&mut self, additional: usize) {
1387+
self.reserve(additional);
1388+
}
13791389
}
13801390

13811391
impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
@@ -1406,4 +1416,14 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
14061416
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
14071417
self.extend(iter.into_iter().cloned());
14081418
}
1419+
1420+
#[inline]
1421+
fn extend_one(&mut self, &item: &'a T) {
1422+
self.push(item);
1423+
}
1424+
1425+
#[inline]
1426+
fn extend_reserve(&mut self, additional: usize) {
1427+
self.reserve(additional);
1428+
}
14091429
}

src/liballoc/collections/btree/map.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1901,13 +1901,23 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
19011901
self.insert(k, v);
19021902
});
19031903
}
1904+
1905+
#[inline]
1906+
fn extend_one(&mut self, (k, v): (K, V)) {
1907+
self.insert(k, v);
1908+
}
19041909
}
19051910

19061911
#[stable(feature = "extend_ref", since = "1.2.0")]
19071912
impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap<K, V> {
19081913
fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
19091914
self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
19101915
}
1916+
1917+
#[inline]
1918+
fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) {
1919+
self.insert(k, v);
1920+
}
19111921
}
19121922

19131923
#[stable(feature = "rust1", since = "1.0.0")]

src/liballoc/collections/btree/set.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1152,13 +1152,23 @@ impl<T: Ord> Extend<T> for BTreeSet<T> {
11521152
self.insert(elem);
11531153
});
11541154
}
1155+
1156+
#[inline]
1157+
fn extend_one(&mut self, elem: T) {
1158+
self.insert(elem);
1159+
}
11551160
}
11561161

11571162
#[stable(feature = "extend_ref", since = "1.2.0")]
11581163
impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet<T> {
11591164
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
11601165
self.extend(iter.into_iter().cloned());
11611166
}
1167+
1168+
#[inline]
1169+
fn extend_one(&mut self, &elem: &'a T) {
1170+
self.insert(elem);
1171+
}
11621172
}
11631173

11641174
#[stable(feature = "rust1", since = "1.0.0")]

src/liballoc/collections/linked_list.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,11 @@ impl<T> Extend<T> for LinkedList<T> {
17481748
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
17491749
<Self as SpecExtend<I>>::spec_extend(self, iter);
17501750
}
1751+
1752+
#[inline]
1753+
fn extend_one(&mut self, elem: T) {
1754+
self.push_back(elem);
1755+
}
17511756
}
17521757

17531758
impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> {
@@ -1767,6 +1772,11 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> {
17671772
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
17681773
self.extend(iter.into_iter().cloned());
17691774
}
1775+
1776+
#[inline]
1777+
fn extend_one(&mut self, &elem: &'a T) {
1778+
self.push_back(elem);
1779+
}
17701780
}
17711781

17721782
#[stable(feature = "rust1", since = "1.0.0")]

src/liballoc/collections/vec_deque.rs

+20
Original file line numberDiff line numberDiff line change
@@ -2881,13 +2881,33 @@ impl<A> Extend<A> for VecDeque<A> {
28812881
}
28822882
}
28832883
}
2884+
2885+
#[inline]
2886+
fn extend_one(&mut self, elem: A) {
2887+
self.push_back(elem);
2888+
}
2889+
2890+
#[inline]
2891+
fn extend_reserve(&mut self, additional: usize) {
2892+
self.reserve(additional);
2893+
}
28842894
}
28852895

28862896
#[stable(feature = "extend_ref", since = "1.2.0")]
28872897
impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque<T> {
28882898
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
28892899
self.extend(iter.into_iter().cloned());
28902900
}
2901+
2902+
#[inline]
2903+
fn extend_one(&mut self, &elem: &T) {
2904+
self.push_back(elem);
2905+
}
2906+
2907+
#[inline]
2908+
fn extend_reserve(&mut self, additional: usize) {
2909+
self.reserve(additional);
2910+
}
28912911
}
28922912

28932913
#[stable(feature = "rust1", since = "1.0.0")]

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#![feature(container_error_extra)]
9494
#![feature(dropck_eyepatch)]
9595
#![feature(exact_size_is_empty)]
96+
#![feature(extend_one)]
9697
#![feature(fmt_internals)]
9798
#![feature(fn_traits)]
9899
#![feature(fundamental)]

src/liballoc/string.rs

+35
Original file line numberDiff line numberDiff line change
@@ -1799,34 +1799,69 @@ impl Extend<char> for String {
17991799
self.reserve(lower_bound);
18001800
iterator.for_each(move |c| self.push(c));
18011801
}
1802+
1803+
#[inline]
1804+
fn extend_one(&mut self, c: char) {
1805+
self.push(c);
1806+
}
1807+
1808+
#[inline]
1809+
fn extend_reserve(&mut self, additional: usize) {
1810+
self.reserve(additional);
1811+
}
18021812
}
18031813

18041814
#[stable(feature = "extend_ref", since = "1.2.0")]
18051815
impl<'a> Extend<&'a char> for String {
18061816
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
18071817
self.extend(iter.into_iter().cloned());
18081818
}
1819+
1820+
#[inline]
1821+
fn extend_one(&mut self, &c: &'a char) {
1822+
self.push(c);
1823+
}
1824+
1825+
#[inline]
1826+
fn extend_reserve(&mut self, additional: usize) {
1827+
self.reserve(additional);
1828+
}
18091829
}
18101830

18111831
#[stable(feature = "rust1", since = "1.0.0")]
18121832
impl<'a> Extend<&'a str> for String {
18131833
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
18141834
iter.into_iter().for_each(move |s| self.push_str(s));
18151835
}
1836+
1837+
#[inline]
1838+
fn extend_one(&mut self, s: &'a str) {
1839+
self.push_str(s);
1840+
}
18161841
}
18171842

18181843
#[stable(feature = "extend_string", since = "1.4.0")]
18191844
impl Extend<String> for String {
18201845
fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
18211846
iter.into_iter().for_each(move |s| self.push_str(&s));
18221847
}
1848+
1849+
#[inline]
1850+
fn extend_one(&mut self, s: String) {
1851+
self.push_str(&s);
1852+
}
18231853
}
18241854

18251855
#[stable(feature = "herd_cows", since = "1.19.0")]
18261856
impl<'a> Extend<Cow<'a, str>> for String {
18271857
fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
18281858
iter.into_iter().for_each(move |s| self.push_str(&s));
18291859
}
1860+
1861+
#[inline]
1862+
fn extend_one(&mut self, s: Cow<'a, str>) {
1863+
self.push_str(&s);
1864+
}
18301865
}
18311866

18321867
/// A convenience impl that delegates to the impl for `&str`.

src/liballoc/vec.rs

+20
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,16 @@ impl<T> Extend<T> for Vec<T> {
20452045
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
20462046
<Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
20472047
}
2048+
2049+
#[inline]
2050+
fn extend_one(&mut self, item: T) {
2051+
self.push(item);
2052+
}
2053+
2054+
#[inline]
2055+
fn extend_reserve(&mut self, additional: usize) {
2056+
self.reserve(additional);
2057+
}
20482058
}
20492059

20502060
// Specialization trait used for Vec::from_iter and Vec::extend
@@ -2316,6 +2326,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> {
23162326
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
23172327
self.spec_extend(iter.into_iter())
23182328
}
2329+
2330+
#[inline]
2331+
fn extend_one(&mut self, &item: &'a T) {
2332+
self.push(item);
2333+
}
2334+
2335+
#[inline]
2336+
fn extend_reserve(&mut self, additional: usize) {
2337+
self.reserve(additional);
2338+
}
23192339
}
23202340

23212341
macro_rules! __impl_slice_eq1 {

src/libcore/iter/traits/collect.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ impl<I: Iterator> IntoIterator for I {
322322
pub trait Extend<A> {
323323
/// Extends a collection with the contents of an iterator.
324324
///
325-
/// As this is the only method for this trait, the [trait-level] docs
325+
/// As this is the only required method for this trait, the [trait-level] docs
326326
/// contain more details.
327327
///
328328
/// [trait-level]: trait.Extend.html
@@ -341,11 +341,26 @@ pub trait Extend<A> {
341341
/// ```
342342
#[stable(feature = "rust1", since = "1.0.0")]
343343
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T);
344+
345+
/// Extends a collection with exactly one element.
346+
#[unstable(feature = "extend_one", issue = "72631")]
347+
fn extend_one(&mut self, item: A) {
348+
self.extend(Some(item));
349+
}
350+
351+
/// Reserves capacity in a collection for the given number of additional elements.
352+
///
353+
/// The default implementation does nothing.
354+
#[unstable(feature = "extend_one", issue = "72631")]
355+
fn extend_reserve(&mut self, additional: usize) {
356+
let _ = additional;
357+
}
344358
}
345359

346360
#[stable(feature = "extend_for_unit", since = "1.28.0")]
347361
impl Extend<()> for () {
348362
fn extend<T: IntoIterator<Item = ()>>(&mut self, iter: T) {
349363
iter.into_iter().for_each(drop)
350364
}
365+
fn extend_one(&mut self, _item: ()) {}
351366
}

src/libcore/iter/traits/iterator.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1700,9 +1700,9 @@ pub trait Iterator {
17001700
) -> impl FnMut((), T) + 'a {
17011701
move |(), x| {
17021702
if f(&x) {
1703-
left.extend(Some(x));
1703+
left.extend_one(x);
17041704
} else {
1705-
right.extend(Some(x));
1705+
right.extend_one(x);
17061706
}
17071707
}
17081708
}
@@ -2675,14 +2675,20 @@ pub trait Iterator {
26752675
us: &'a mut impl Extend<B>,
26762676
) -> impl FnMut((), (A, B)) + 'a {
26772677
move |(), (t, u)| {
2678-
ts.extend(Some(t));
2679-
us.extend(Some(u));
2678+
ts.extend_one(t);
2679+
us.extend_one(u);
26802680
}
26812681
}
26822682

26832683
let mut ts: FromA = Default::default();
26842684
let mut us: FromB = Default::default();
26852685

2686+
let (lower_bound, _) = self.size_hint();
2687+
if lower_bound > 0 {
2688+
ts.extend_reserve(lower_bound);
2689+
us.extend_reserve(lower_bound);
2690+
}
2691+
26862692
self.fold((), extend(&mut ts, &mut us));
26872693

26882694
(ts, us)

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#![feature(test)]
2323
#![feature(associated_type_bounds)]
2424
#![feature(thread_id_value)]
25+
#![feature(extend_one)]
2526
#![allow(rustc::default_hash_types)]
2627

2728
#[macro_use]

src/librustc_data_structures/thin_vec.rs

+14
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ impl<T> Extend<T> for ThinVec<T> {
5353
ThinVec(None) => *self = iter.into_iter().collect::<Vec<_>>().into(),
5454
}
5555
}
56+
57+
fn extend_one(&mut self, item: T) {
58+
match *self {
59+
ThinVec(Some(ref mut vec)) => vec.push(item),
60+
ThinVec(None) => *self = vec![item].into(),
61+
}
62+
}
63+
64+
fn extend_reserve(&mut self, additional: usize) {
65+
match *self {
66+
ThinVec(Some(ref mut vec)) => vec.reserve(additional),
67+
ThinVec(None) => *self = Vec::with_capacity(additional).into(),
68+
}
69+
}
5670
}
5771

5872
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ThinVec<T> {

src/librustc_index/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(const_if_match)]
33
#![feature(const_fn)]
44
#![feature(const_panic)]
5+
#![feature(extend_one)]
56
#![feature(unboxed_closures)]
67
#![feature(test)]
78
#![feature(fn_traits)]

src/librustc_index/vec.rs

+10
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,16 @@ impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
736736
fn extend<J: IntoIterator<Item = T>>(&mut self, iter: J) {
737737
self.raw.extend(iter);
738738
}
739+
740+
#[inline]
741+
fn extend_one(&mut self, item: T) {
742+
self.raw.push(item);
743+
}
744+
745+
#[inline]
746+
fn extend_reserve(&mut self, additional: usize) {
747+
self.raw.reserve(additional);
748+
}
739749
}
740750

741751
impl<I: Idx, T> FromIterator<T> for IndexVec<I, T> {

src/librustc_infer/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#![feature(bool_to_option)]
1717
#![feature(box_patterns)]
1818
#![feature(box_syntax)]
19+
#![feature(extend_one)]
1920
#![feature(never_type)]
2021
#![feature(or_patterns)]
2122
#![feature(range_is_empty)]

src/librustc_infer/traits/util.rs

+8
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
8787
self.insert(pred.as_ref());
8888
}
8989
}
90+
91+
fn extend_one(&mut self, pred: T) {
92+
self.insert(pred.as_ref());
93+
}
94+
95+
fn extend_reserve(&mut self, additional: usize) {
96+
Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
97+
}
9098
}
9199

92100
///////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)