@@ -492,131 +492,150 @@ impl Extend<()> for () {
492492 fn extend_one ( & mut self , _item : ( ) ) { }
493493}
494494
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) , ) * ) => {
526500
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+ }
531538
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+ }
536542
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+ }
545546
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+ }
561553 }
562- }
563554
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+ }
569558
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+ }
572573
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+ }
576578
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+ }
587581
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) ,* ) ;
604589 }
605590 }
606591
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+ }
608608
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( ) ;
614610
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+ }
619616
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+ }
621623 }
624+
625+ } ;
622626}
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