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