Skip to content

Commit 2de5709

Browse files
committed
Special impl for 1-tuple, more efficient by simple delegation to field's extend impl
1 parent 75b23cf commit 2de5709

File tree

1 file changed

+111
-83
lines changed

1 file changed

+111
-83
lines changed

library/core/src/iter/traits/collect.rs

Lines changed: 111 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,15 @@ macro_rules! spec_tuple_impl {
478478
$($remainder,)*
479479
);
480480
};
481-
([$($params_:tt)*]) => {};
481+
( [$($params_:tt)*] ) => { };
482482
(
483483
$SpecTupleExtendN:ident, $default_extend_tuple_n:ident,
484484
$params:tt
485485
) => {
486486
spec_tuple_impl!(
487487
$SpecTupleExtendN,
488488
$default_extend_tuple_n,
489+
#special_case_1_tuple
489490
#[doc(fake_variadic)]
490491
#[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for \
491492
1- and 3- through 12-ary tuples were stabilized after 2-tuples, in \
@@ -500,12 +501,14 @@ macro_rules! spec_tuple_impl {
500501
spec_tuple_impl!(
501502
$SpecTupleExtendN,
502503
$default_extend_tuple_n,
504+
#normal_case
503505
#[doc(hidden)]
504506
=> $($params,)+
505507
);
506508
};
507509
(
508-
$SpecTupleExtendN:ident, $default_extend_tuple_n:ident, #[$meta:meta]
510+
$SpecTupleExtendN:ident, $default_extend_tuple_n:ident, #$maybe_special_case:tt
511+
#[$meta:meta]
509512
$(#[$doctext:meta])? => $(
510513
(
511514
$Ts:ident, $var_names:ident, $ExtendTs:ident, $cnts:tt
@@ -519,32 +522,15 @@ macro_rules! spec_tuple_impl {
519522
where
520523
$($ExtendTs: Extend<$Ts>,)*
521524
{
522-
/// Allows to `extend` a tuple of collections that also implement `Extend`.
523-
///
524-
/// See also: [`Iterator::unzip`]
525-
///
526-
/// # Examples
527-
/// ```
528-
/// // Example given for a 2-tuple, but 1- through 12-tuples are supported
529-
/// let mut tuple = (vec![0], vec![1]);
530-
/// tuple.extend([(2, 3), (4, 5), (6, 7)]);
531-
/// assert_eq!(tuple.0, [0, 2, 4, 6]);
532-
/// assert_eq!(tuple.1, [1, 3, 5, 7]);
533-
///
534-
/// // also allows for arbitrarily nested tuples as elements
535-
/// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
536-
/// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
537-
///
538-
/// let (a, (b, c)) = nested_tuple;
539-
/// assert_eq!(a, [1, 4, 7]);
540-
/// assert_eq!(b, [2, 5, 8]);
541-
/// assert_eq!(c, [3, 6, 9]);
542-
/// ```
543-
fn extend<I: IntoIterator<Item = ($($Ts,)*)>>(&mut self, into_iter: I) {
544-
let ($($var_names,)*) = self;
545-
let iter = into_iter.into_iter();
546-
$SpecTupleExtendN::extend(iter, $($var_names,)*);
547-
}
525+
526+
spec_tuple_impl!(#$maybe_special_case
527+
528+
fn extend<I: IntoIterator<Item = ($($Ts,)*)>>(&mut self, into_iter: I) {
529+
let ($($var_names,)*) = self;
530+
let iter = into_iter.into_iter();
531+
$SpecTupleExtendN::extend(iter, $($var_names,)*);
532+
}
533+
);
548534

549535
fn extend_one(&mut self, item: ($($Ts,)*)) {
550536
$(self.$cnts.extend_one(item.$cnts);)*
@@ -562,75 +548,78 @@ macro_rules! spec_tuple_impl {
562548
}
563549
}
564550

565-
trait $SpecTupleExtendN<$($Ts),*> {
566-
fn extend(self, $($var_names: &mut $Ts,)*);
567-
}
551+
spec_tuple_impl!(#$maybe_special_case
568552

569-
fn $default_extend_tuple_n<$($Ts,)* $($ExtendTs,)*>(
570-
iter: impl Iterator<Item = ($($Ts,)*)>,
571-
$($var_names: &mut $ExtendTs,)*
572-
) where
573-
$($ExtendTs: Extend<$Ts>,)*
574-
{
575-
fn extend<'a, $($Ts,)*>(
576-
$($var_names: &'a mut impl Extend<$Ts>,)*
577-
) -> impl FnMut((), ($($Ts,)*)) + 'a {
578-
#[allow(non_snake_case)]
579-
move |(), ($($ExtendTs,)*)| {
580-
$($var_names.extend_one($ExtendTs);)*
581-
}
553+
trait $SpecTupleExtendN<$($Ts),*> {
554+
fn extend(self, $($var_names: &mut $Ts,)*);
582555
}
583556

584-
let (lower_bound, _) = iter.size_hint();
585-
if lower_bound > 0 {
586-
$($var_names.extend_reserve(lower_bound);)*
587-
}
588-
589-
iter.fold((), extend($($var_names,)*));
590-
}
591-
592-
impl<$($Ts,)* $($ExtendTs,)* Iter> $SpecTupleExtendN<$($ExtendTs),*> for Iter
593-
where
594-
$($ExtendTs: Extend<$Ts>,)*
595-
Iter: Iterator<Item = ($($Ts,)*)>,
596-
{
597-
default fn extend(self, $($var_names: &mut $ExtendTs),*) {
598-
$default_extend_tuple_n(self, $($var_names),*);
599-
}
600-
}
601-
602-
impl<$($Ts,)* $($ExtendTs,)* Iter> $SpecTupleExtendN<$($ExtendTs),*> for Iter
603-
where
604-
$($ExtendTs: Extend<$Ts>,)*
605-
Iter: TrustedLen<Item = ($($Ts,)*)>,
606-
{
607-
fn extend(self, $($var_names: &mut $ExtendTs,)*) {
557+
fn $default_extend_tuple_n<$($Ts,)* $($ExtendTs,)*>(
558+
iter: impl Iterator<Item = ($($Ts,)*)>,
559+
$($var_names: &mut $ExtendTs,)*
560+
) where
561+
$($ExtendTs: Extend<$Ts>,)*
562+
{
608563
fn extend<'a, $($Ts,)*>(
609564
$($var_names: &'a mut impl Extend<$Ts>,)*
610565
) -> impl FnMut((), ($($Ts,)*)) + 'a {
611566
#[allow(non_snake_case)]
612-
// SAFETY: We reserve enough space for the `size_hint`, and the iterator is
613-
// `TrustedLen` so its `size_hint` is exact.
614-
move |(), ($($ExtendTs,)*)| unsafe {
615-
$($var_names.extend_one_unchecked($ExtendTs);)*
567+
move |(), ($($ExtendTs,)*)| {
568+
$($var_names.extend_one($ExtendTs);)*
616569
}
617570
}
618571

619-
let (lower_bound, upper_bound) = self.size_hint();
620-
621-
if upper_bound.is_none() {
622-
// We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
623-
$default_extend_tuple_n(self, $($var_names,)*);
624-
return;
625-
}
626-
572+
let (lower_bound, _) = iter.size_hint();
627573
if lower_bound > 0 {
628574
$($var_names.extend_reserve(lower_bound);)*
629575
}
630576

631-
self.fold((), extend($($var_names,)*));
577+
iter.fold((), extend($($var_names,)*));
632578
}
633-
}
579+
580+
impl<$($Ts,)* $($ExtendTs,)* Iter> $SpecTupleExtendN<$($ExtendTs),*> for Iter
581+
where
582+
$($ExtendTs: Extend<$Ts>,)*
583+
Iter: Iterator<Item = ($($Ts,)*)>,
584+
{
585+
default fn extend(self, $($var_names: &mut $ExtendTs),*) {
586+
$default_extend_tuple_n(self, $($var_names),*);
587+
}
588+
}
589+
590+
impl<$($Ts,)* $($ExtendTs,)* Iter> $SpecTupleExtendN<$($ExtendTs),*> for Iter
591+
where
592+
$($ExtendTs: Extend<$Ts>,)*
593+
Iter: TrustedLen<Item = ($($Ts,)*)>,
594+
{
595+
fn extend(self, $($var_names: &mut $ExtendTs,)*) {
596+
fn extend<'a, $($Ts,)*>(
597+
$($var_names: &'a mut impl Extend<$Ts>,)*
598+
) -> impl FnMut((), ($($Ts,)*)) + 'a {
599+
#[allow(non_snake_case)]
600+
// SAFETY: We reserve enough space for the `size_hint`, and the iterator is
601+
// `TrustedLen` so its `size_hint` is exact.
602+
move |(), ($($ExtendTs,)*)| unsafe {
603+
$($var_names.extend_one_unchecked($ExtendTs);)*
604+
}
605+
}
606+
607+
let (lower_bound, upper_bound) = self.size_hint();
608+
609+
if upper_bound.is_none() {
610+
// We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
611+
$default_extend_tuple_n(self, $($var_names,)*);
612+
return;
613+
}
614+
615+
if lower_bound > 0 {
616+
$($var_names.extend_reserve(lower_bound);)*
617+
}
618+
619+
self.fold((), extend($($var_names,)*));
620+
}
621+
}
622+
);
634623

635624
/// This implementation turns an iterator of tuples into a tuple of types which implement
636625
/// [`Default`] and [`Extend`].
@@ -666,7 +655,46 @@ macro_rules! spec_tuple_impl {
666655
res
667656
}
668657
}
669-
658+
};
659+
(
660+
#special_case_1_tuple fn
661+
$($t:tt)*
662+
) => {
663+
/// Allows to `extend` a tuple of collections that also implement `Extend`.
664+
///
665+
/// See also: [`Iterator::unzip`]
666+
///
667+
/// # Examples
668+
/// ```
669+
/// // Example given for a 2-tuple, but 1- through 12-tuples are supported
670+
/// let mut tuple = (vec![0], vec![1]);
671+
/// tuple.extend([(2, 3), (4, 5), (6, 7)]);
672+
/// assert_eq!(tuple.0, [0, 2, 4, 6]);
673+
/// assert_eq!(tuple.1, [1, 3, 5, 7]);
674+
///
675+
/// // also allows for arbitrarily nested tuples as elements
676+
/// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
677+
/// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
678+
///
679+
/// let (a, (b, c)) = nested_tuple;
680+
/// assert_eq!(a, [1, 4, 7]);
681+
/// assert_eq!(b, [2, 5, 8]);
682+
/// assert_eq!(c, [3, 6, 9]);
683+
/// ```
684+
fn extend<I: IntoIterator<Item = (T,)>>(&mut self, into_iter: I) {
685+
self.0.extend(into_iter.into_iter().map(|(a,)| a));
686+
}
687+
};
688+
(
689+
#special_case_1_tuple $($t:tt)*
690+
) => {
691+
// no specialization traits
692+
};
693+
(
694+
#normal_case
695+
$($t:tt)*
696+
) => {
697+
$($t)*
670698
};
671699
}
672700

0 commit comments

Comments
 (0)