Skip to content

Commit 915cc87

Browse files
JohnTitorgitbot
authored and
gitbot
committed
Rollup merge of rust-lang#85835 - Seppel3210:master, r=yaahc
Implement Extend<(A, B)> for (Extend<A>, Extend<B>) I oriented myself at the implementation of `Iterator::unzip` and also rewrote the impl in terms of `(A, B)::extend` after that. Since (A, B) now also implements Extend we could also mention in the documentation of unzip that it can do "nested unzipping" (you could unzip `Iterator<Item=(A, (B, C))>` into `(Vec<A>, (Vec<B>, Vec<C>))` for example) but I'm not sure of that so I'm asking here 🙂 (P.S. I saw a couple of people asking if there is an unzip3 but there isn't. So this could be a way to get equivalent functionality)
2 parents 6414dac + 7c5053c commit 915cc87

File tree

2 files changed

+43
-22
lines changed

2 files changed

+43
-22
lines changed

core/src/iter/traits/collect.rs

+40
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,43 @@ impl Extend<()> for () {
359359
}
360360
fn extend_one(&mut self, _item: ()) {}
361361
}
362+
363+
#[stable(feature = "extend_for_tuple", since = "1.54.0")]
364+
impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
365+
where
366+
ExtendA: Extend<A>,
367+
ExtendB: Extend<B>,
368+
{
369+
fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
370+
let (a, b) = self;
371+
let iter = into_iter.into_iter();
372+
373+
fn extend<'a, A, B>(
374+
a: &'a mut impl Extend<A>,
375+
b: &'a mut impl Extend<B>,
376+
) -> impl FnMut((), (A, B)) + 'a {
377+
move |(), (t, u)| {
378+
a.extend_one(t);
379+
b.extend_one(u);
380+
}
381+
}
382+
383+
let (lower_bound, _) = iter.size_hint();
384+
if lower_bound > 0 {
385+
a.extend_reserve(lower_bound);
386+
b.extend_reserve(lower_bound);
387+
}
388+
389+
iter.fold((), extend(a, b));
390+
}
391+
392+
fn extend_one(&mut self, item: (A, B)) {
393+
self.0.extend_one(item.0);
394+
self.1.extend_one(item.1);
395+
}
396+
397+
fn extend_reserve(&mut self, additional: usize) {
398+
self.0.extend_reserve(additional);
399+
self.1.extend_reserve(additional);
400+
}
401+
}

core/src/iter/traits/iterator.rs

+3-22
Original file line numberDiff line numberDiff line change
@@ -2860,28 +2860,9 @@ pub trait Iterator {
28602860
FromB: Default + Extend<B>,
28612861
Self: Sized + Iterator<Item = (A, B)>,
28622862
{
2863-
fn extend<'a, A, B>(
2864-
ts: &'a mut impl Extend<A>,
2865-
us: &'a mut impl Extend<B>,
2866-
) -> impl FnMut((), (A, B)) + 'a {
2867-
move |(), (t, u)| {
2868-
ts.extend_one(t);
2869-
us.extend_one(u);
2870-
}
2871-
}
2872-
2873-
let mut ts: FromA = Default::default();
2874-
let mut us: FromB = Default::default();
2875-
2876-
let (lower_bound, _) = self.size_hint();
2877-
if lower_bound > 0 {
2878-
ts.extend_reserve(lower_bound);
2879-
us.extend_reserve(lower_bound);
2880-
}
2881-
2882-
self.fold((), extend(&mut ts, &mut us));
2883-
2884-
(ts, us)
2863+
let mut unzipped: (FromA, FromB) = Default::default();
2864+
unzipped.extend(self);
2865+
unzipped
28852866
}
28862867

28872868
/// Creates an iterator which copies all of its elements.

0 commit comments

Comments
 (0)