@@ -1680,12 +1680,55 @@ impl<'a> TraitDef<'a> {
1680
1680
1681
1681
// helpful premade recipes
1682
1682
1683
+ pub fn cs_fold_fields < ' a , F > ( use_foldl : bool ,
1684
+ mut f : F ,
1685
+ base : P < Expr > ,
1686
+ cx : & mut ExtCtxt ,
1687
+ all_fields : & [ FieldInfo < ' a > ] )
1688
+ -> P < Expr >
1689
+ where F : FnMut ( & mut ExtCtxt , Span , P < Expr > , P < Expr > , & [ P < Expr > ] ) -> P < Expr >
1690
+ {
1691
+ if use_foldl {
1692
+ all_fields. iter ( ) . fold ( base, |old, field| {
1693
+ f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1694
+ } )
1695
+ } else {
1696
+ all_fields. iter ( ) . rev ( ) . fold ( base, |old, field| {
1697
+ f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1698
+ } )
1699
+ }
1700
+ }
1701
+
1702
+ pub fn cs_fold_enumnonmatch ( mut enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1703
+ cx : & mut ExtCtxt ,
1704
+ trait_span : Span ,
1705
+ substructure : & Substructure )
1706
+ -> P < Expr >
1707
+ {
1708
+ match * substructure. fields {
1709
+ EnumNonMatchingCollapsed ( ref all_args, _, tuple) => {
1710
+ enum_nonmatch_f ( cx,
1711
+ trait_span,
1712
+ ( & all_args[ ..] , tuple) ,
1713
+ substructure. nonself_args )
1714
+ }
1715
+ _ => cx. span_bug ( trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed" )
1716
+ }
1717
+ }
1718
+
1719
+ pub fn cs_fold_static ( cx : & mut ExtCtxt ,
1720
+ trait_span : Span )
1721
+ -> P < Expr >
1722
+ {
1723
+ cx. span_bug ( trait_span, "static function in `derive`" )
1724
+ }
1725
+
1683
1726
/// Fold the fields. `use_foldl` controls whether this is done
1684
1727
/// left-to-right (`true`) or right-to-left (`false`).
1685
1728
pub fn cs_fold < F > ( use_foldl : bool ,
1686
- mut f : F ,
1729
+ f : F ,
1687
1730
base : P < Expr > ,
1688
- mut enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1731
+ enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1689
1732
cx : & mut ExtCtxt ,
1690
1733
trait_span : Span ,
1691
1734
substructure : & Substructure )
@@ -1695,26 +1738,65 @@ pub fn cs_fold<F>(use_foldl: bool,
1695
1738
match * substructure. fields {
1696
1739
EnumMatching ( .., ref all_fields) |
1697
1740
Struct ( _, ref all_fields) => {
1698
- if use_foldl {
1699
- all_fields. iter ( ) . fold ( base, |old, field| {
1700
- f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1701
- } )
1702
- } else {
1703
- all_fields. iter ( ) . rev ( ) . fold ( base, |old, field| {
1704
- f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1705
- } )
1706
- }
1741
+ cs_fold_fields ( use_foldl, f, base, cx, all_fields)
1707
1742
}
1708
- EnumNonMatchingCollapsed ( ref all_args , _ , tuple ) => {
1709
- enum_nonmatch_f ( cx,
1710
- trait_span ,
1711
- ( & all_args [ .. ] , tuple ) ,
1712
- substructure . nonself_args )
1743
+ EnumNonMatchingCollapsed ( .. ) => {
1744
+ cs_fold_enumnonmatch ( enum_nonmatch_f , cx, trait_span , substructure )
1745
+ }
1746
+ StaticEnum ( .. ) | StaticStruct ( .. ) => {
1747
+ cs_fold_static ( cx , trait_span )
1713
1748
}
1714
- StaticEnum ( ..) | StaticStruct ( ..) => cx. span_bug ( trait_span, "static function in `derive`" ) ,
1715
1749
}
1716
1750
}
1717
1751
1752
+ /// Function to fold over fields, with three cases, to generate more efficient and concise code.
1753
+ /// When the `substructure` has grouped fields, there are two cases:
1754
+ /// Zero fields: call the base case function with None (like the usual base case of `cs_fold`).
1755
+ /// One or more fields: call the base case function on the first value (which depends on
1756
+ /// `use_fold`), and use that as the base case. Then perform `cs_fold` on the remainder of the
1757
+ /// fields.
1758
+ /// When the `substructure` is a `EnumNonMatchingCollapsed`, the result of `enum_nonmatch_f`
1759
+ /// is returned. Statics may not be folded over.
1760
+ /// See `cs_op` in `partial_ord.rs` for a model example.
1761
+ pub fn cs_fold1 < F , B > ( use_foldl : bool ,
1762
+ f : F ,
1763
+ mut b : B ,
1764
+ enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1765
+ cx : & mut ExtCtxt ,
1766
+ trait_span : Span ,
1767
+ substructure : & Substructure )
1768
+ -> P < Expr >
1769
+ where F : FnMut ( & mut ExtCtxt , Span , P < Expr > , P < Expr > , & [ P < Expr > ] ) -> P < Expr > ,
1770
+ B : FnMut ( & mut ExtCtxt , Option < ( Span , P < Expr > , & [ P < Expr > ] ) > ) -> P < Expr >
1771
+ {
1772
+ match * substructure. fields {
1773
+ EnumMatching ( .., ref all_fields) |
1774
+ Struct ( _, ref all_fields) => {
1775
+ let ( base, all_fields) = match ( all_fields. is_empty ( ) , use_foldl) {
1776
+ ( false , true ) => {
1777
+ let field = & all_fields[ 0 ] ;
1778
+ let args = ( field. span , field. self_ . clone ( ) , & field. other [ ..] ) ;
1779
+ ( b ( cx, Some ( args) ) , & all_fields[ 1 ..] )
1780
+ }
1781
+ ( false , false ) => {
1782
+ let idx = all_fields. len ( ) - 1 ;
1783
+ let field = & all_fields[ idx] ;
1784
+ let args = ( field. span , field. self_ . clone ( ) , & field. other [ ..] ) ;
1785
+ ( b ( cx, Some ( args) ) , & all_fields[ ..idx] )
1786
+ }
1787
+ ( true , _) => ( b ( cx, None ) , & all_fields[ ..] )
1788
+ } ;
1789
+
1790
+ cs_fold_fields ( use_foldl, f, base, cx, all_fields)
1791
+ }
1792
+ EnumNonMatchingCollapsed ( ..) => {
1793
+ cs_fold_enumnonmatch ( enum_nonmatch_f, cx, trait_span, substructure)
1794
+ }
1795
+ StaticEnum ( ..) | StaticStruct ( ..) => {
1796
+ cs_fold_static ( cx, trait_span)
1797
+ }
1798
+ }
1799
+ }
1718
1800
1719
1801
/// Call the method that is being derived on all the fields, and then
1720
1802
/// process the collected results. i.e.
0 commit comments