@@ -492,131 +492,150 @@ impl Extend<()> for () {
492
492
fn extend_one(&mut self, _item: ()) {}
493
493
}
494
494
495
- #[stable(feature = "extend_for_tuple", since = "1.56.0")]
496
- impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
497
- where
498
- ExtendA: Extend<A>,
499
- ExtendB: Extend<B>,
500
- {
501
- /// Allows to `extend` a tuple of collections that also implement `Extend`.
502
- ///
503
- /// See also: [`Iterator::unzip`]
504
- ///
505
- /// # Examples
506
- /// ```
507
- /// let mut tuple = (vec![0], vec![1]);
508
- /// tuple.extend([(2, 3), (4, 5), (6, 7)]);
509
- /// assert_eq!(tuple.0, [0, 2, 4, 6]);
510
- /// assert_eq!(tuple.1, [1, 3, 5, 7]);
511
- ///
512
- /// // also allows for arbitrarily nested tuples as elements
513
- /// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
514
- /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
515
- ///
516
- /// let (a, (b, c)) = nested_tuple;
517
- /// assert_eq!(a, [1, 4, 7]);
518
- /// assert_eq!(b, [2, 5, 8]);
519
- /// assert_eq!(c, [3, 6, 9]);
520
- /// ```
521
- fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
522
- let (a, b) = self;
523
- let iter = into_iter.into_iter();
524
- SpecTupleExtend::extend(iter, a, b);
525
- }
495
+ macro_rules! spec_tuple_impl {
496
+ ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => {
497
+ spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),);
498
+ };
499
+ ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => {
526
500
527
- fn extend_one(&mut self, item: (A, B)) {
528
- self.0.extend_one(item.0);
529
- self.1.extend_one(item.1);
530
- }
501
+ spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*);
502
+ spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*);
503
+ };
504
+ ($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => {
505
+ #[$meta]
506
+ $(#[$doctext])?
507
+ #[stable(feature = "extend_for_tuple", since = "1.56.0")]
508
+ impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*)
509
+ where
510
+ $($extend_ty_names: Extend<$ty_names>,)*
511
+ {
512
+ /// Allows to `extend` a tuple of collections that also implement `Extend`.
513
+ ///
514
+ /// See also: [`Iterator::unzip`]
515
+ ///
516
+ /// # Examples
517
+ /// ```
518
+ /// // Example given for a 2-tuple, but 1- through 12-tuples are supported
519
+ /// let mut tuple = (vec![0], vec![1]);
520
+ /// tuple.extend([(2, 3), (4, 5), (6, 7)]);
521
+ /// assert_eq!(tuple.0, [0, 2, 4, 6]);
522
+ /// assert_eq!(tuple.1, [1, 3, 5, 7]);
523
+ ///
524
+ /// // also allows for arbitrarily nested tuples as elements
525
+ /// let mut nested_tuple = (vec![1], (vec![2], vec![3]));
526
+ /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]);
527
+ ///
528
+ /// let (a, (b, c)) = nested_tuple;
529
+ /// assert_eq!(a, [1, 4, 7]);
530
+ /// assert_eq!(b, [2, 5, 8]);
531
+ /// assert_eq!(c, [3, 6, 9]);
532
+ /// ```
533
+ fn extend<T: IntoIterator<Item = ($($ty_names,)*)>>(&mut self, into_iter: T) {
534
+ let ($($var_names,)*) = self;
535
+ let iter = into_iter.into_iter();
536
+ $trait_name::extend(iter, $($var_names,)*);
537
+ }
531
538
532
- fn extend_reserve(&mut self, additional: usize) {
533
- self.0.extend_reserve(additional);
534
- self.1.extend_reserve(additional);
535
- }
539
+ fn extend_one(&mut self, item: ($($ty_names,)*)) {
540
+ $(self.$cnts.extend_one(item.$cnts);)*
541
+ }
536
542
537
- unsafe fn extend_one_unchecked(&mut self, item: (A, B)) {
538
- // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
539
- unsafe {
540
- self.0.extend_one_unchecked(item.0);
541
- self.1.extend_one_unchecked(item.1);
542
- }
543
- }
544
- }
543
+ fn extend_reserve(&mut self, additional: usize) {
544
+ $(self.$cnts.extend_reserve(additional);)*
545
+ }
545
546
546
- fn default_extend_tuple<A, B, ExtendA, ExtendB>(
547
- iter: impl Iterator<Item = (A, B)>,
548
- a: &mut ExtendA,
549
- b: &mut ExtendB,
550
- ) where
551
- ExtendA: Extend<A>,
552
- ExtendB: Extend<B>,
553
- {
554
- fn extend<'a, A, B>(
555
- a: &'a mut impl Extend<A>,
556
- b: &'a mut impl Extend<B>,
557
- ) -> impl FnMut((), (A, B)) + 'a {
558
- move |(), (t, u)| {
559
- a.extend_one(t);
560
- b.extend_one(u);
547
+ unsafe fn extend_one_unchecked(&mut self, item: ($($ty_names,)*)) {
548
+ // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
549
+ unsafe {
550
+ $(self.$cnts.extend_one_unchecked(item.$cnts);)*
551
+ }
552
+ }
561
553
}
562
- }
563
554
564
- let (lower_bound, _) = iter.size_hint();
565
- if lower_bound > 0 {
566
- a.extend_reserve(lower_bound);
567
- b.extend_reserve(lower_bound);
568
- }
555
+ trait $trait_name<$($ty_names),*> {
556
+ fn extend(self, $($var_names: &mut $ty_names,)*);
557
+ }
569
558
570
- iter.fold((), extend(a, b));
571
- }
559
+ fn $default_fn_name<$($ty_names,)* $($extend_ty_names,)*>(
560
+ iter: impl Iterator<Item = ($($ty_names,)*)>,
561
+ $($var_names: &mut $extend_ty_names,)*
562
+ ) where
563
+ $($extend_ty_names: Extend<$ty_names>,)*
564
+ {
565
+ fn extend<'a, $($ty_names,)*>(
566
+ $($var_names: &'a mut impl Extend<$ty_names>,)*
567
+ ) -> impl FnMut((), ($($ty_names,)*)) + 'a {
568
+ #[allow(non_snake_case)]
569
+ move |(), ($($extend_ty_names,)*)| {
570
+ $($var_names.extend_one($extend_ty_names);)*
571
+ }
572
+ }
572
573
573
- trait SpecTupleExtend<A, B> {
574
- fn extend(self, a: &mut A, b: &mut B);
575
- }
574
+ let (lower_bound, _) = iter.size_hint();
575
+ if lower_bound > 0 {
576
+ $($var_names.extend_reserve(lower_bound);)*
577
+ }
576
578
577
- impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
578
- where
579
- ExtendA: Extend<A>,
580
- ExtendB: Extend<B>,
581
- Iter: Iterator<Item = (A, B)>,
582
- {
583
- default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
584
- default_extend_tuple(self, a, b);
585
- }
586
- }
579
+ iter.fold((), extend($($var_names,)*));
580
+ }
587
581
588
- impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
589
- where
590
- ExtendA: Extend<A>,
591
- ExtendB: Extend<B>,
592
- Iter: TrustedLen<Item = (A, B)>,
593
- {
594
- fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
595
- fn extend<'a, A, B>(
596
- a: &'a mut impl Extend<A>,
597
- b: &'a mut impl Extend<B>,
598
- ) -> impl FnMut((), (A, B)) + 'a {
599
- // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
600
- // so its `size_hint` is exact.
601
- move |(), (t, u)| unsafe {
602
- a.extend_one_unchecked(t);
603
- b.extend_one_unchecked(u);
582
+ impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
583
+ where
584
+ $($extend_ty_names: Extend<$ty_names>,)*
585
+ Iter: Iterator<Item = ($($ty_names,)*)>,
586
+ {
587
+ default fn extend(self, $($var_names: &mut $extend_ty_names),*) {
588
+ $default_fn_name(self, $($var_names),*);
604
589
}
605
590
}
606
591
607
- let (lower_bound, upper_bound) = self.size_hint();
592
+ impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
593
+ where
594
+ $($extend_ty_names: Extend<$ty_names>,)*
595
+ Iter: TrustedLen<Item = ($($ty_names,)*)>,
596
+ {
597
+ fn extend(self, $($var_names: &mut $extend_ty_names,)*) {
598
+ fn extend<'a, $($ty_names,)*>(
599
+ $($var_names: &'a mut impl Extend<$ty_names>,)*
600
+ ) -> impl FnMut((), ($($ty_names,)*)) + 'a {
601
+ #[allow(non_snake_case)]
602
+ // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
603
+ // so its `size_hint` is exact.
604
+ move |(), ($($extend_ty_names,)*)| unsafe {
605
+ $($var_names.extend_one_unchecked($extend_ty_names);)*
606
+ }
607
+ }
608
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(self, a, b);
612
- return;
613
- }
609
+ let (lower_bound, upper_bound) = self.size_hint();
614
610
615
- if lower_bound > 0 {
616
- a.extend_reserve(lower_bound);
617
- b.extend_reserve(lower_bound);
618
- }
611
+ if upper_bound.is_none() {
612
+ // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
613
+ $default_fn_name(self, $($var_names,)*);
614
+ return;
615
+ }
619
616
620
- self.fold((), extend(a, b));
617
+ if lower_bound > 0 {
618
+ $($var_names.extend_reserve(lower_bound);)*
619
+ }
620
+
621
+ self.fold((), extend($($var_names,)*));
622
+ }
621
623
}
624
+
625
+ };
622
626
}
627
+
628
+ spec_tuple_impl!(
629
+ (L, l, EL, TraitL, default_extend_tuple_l, 11),
630
+ (K, k, EK, TraitK, default_extend_tuple_k, 10),
631
+ (J, j, EJ, TraitJ, default_extend_tuple_j, 9),
632
+ (I, i, EI, TraitI, default_extend_tuple_i, 8),
633
+ (H, h, EH, TraitH, default_extend_tuple_h, 7),
634
+ (G, g, EG, TraitG, default_extend_tuple_g, 6),
635
+ (F, f, EF, TraitF, default_extend_tuple_f, 5),
636
+ (E, e, EE, TraitE, default_extend_tuple_e, 4),
637
+ (D, d, ED, TraitD, default_extend_tuple_d, 3),
638
+ (C, c, EC, TraitC, default_extend_tuple_c, 2),
639
+ (B, b, EB, TraitB, default_extend_tuple_b, 1),
640
+ (A, a, EA, TraitA, default_extend_tuple_a, 0),
641
+ );
0 commit comments