]> git.lizzy.rs Git - rust.git/blob - tests/ui/macros/type-macros-hlist.rs
Rollup merge of #106854 - steffahn:drop_linear_arc_rebased, r=Mark-Simulacrum
[rust.git] / tests / ui / macros / type-macros-hlist.rs
1 // run-pass
2 #![allow(unused_macro_rules)]
3
4 use std::ops::*;
5
6 #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
7 struct Nil;
8  // empty HList
9 #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
10 struct Cons<H, T: HList>(H, T);
11  // cons cell of HList
12
13  // trait to classify valid HLists
14 trait HList { }
15 impl HList for Nil { }
16 impl <H, T: HList> HList for Cons<H, T> { }
17
18 // term-level macro for HLists
19 macro_rules! hlist({  } => { Nil } ; { $ head : expr } => {
20                    Cons ( $ head , Nil ) } ; {
21                    $ head : expr , $ ( $ tail : expr ) , * } => {
22                    Cons ( $ head , hlist ! ( $ ( $ tail ) , * ) ) } ;);
23
24 // type-level macro for HLists
25 macro_rules! HList({  } => { Nil } ; { $ head : ty } => {
26                    Cons < $ head , Nil > } ; {
27                    $ head : ty , $ ( $ tail : ty ) , * } => {
28                    Cons < $ head , HList ! ( $ ( $ tail ) , * ) > } ;);
29
30 // nil case for HList append
31 impl <Ys: HList> Add<Ys> for Nil {
32     type
33     Output
34     =
35     Ys;
36
37     fn add(self, rhs: Ys) -> Ys { rhs }
38 }
39
40 // cons case for HList append
41 impl <Rec: HList + Sized, X, Xs: HList, Ys: HList> Add<Ys> for Cons<X, Xs>
42  where Xs: Add<Ys, Output = Rec> {
43     type
44     Output
45     =
46     Cons<X, Rec>;
47
48     fn add(self, rhs: Ys) -> Cons<X, Rec> { Cons(self.0, self.1 + rhs) }
49 }
50
51 // type macro Expr allows us to expand the + operator appropriately
52 macro_rules! Expr({ ( $ ( $ LHS : tt ) + ) } => { Expr ! ( $ ( $ LHS ) + ) } ;
53                   { HList ! [ $ ( $ LHS : tt ) * ] + $ ( $ RHS : tt ) + } => {
54                   < Expr ! ( HList ! [ $ ( $ LHS ) * ] ) as Add < Expr ! (
55                   $ ( $ RHS ) + ) >> :: Output } ; {
56                   $ LHS : tt + $ ( $ RHS : tt ) + } => {
57                   < Expr ! ( $ LHS ) as Add < Expr ! ( $ ( $ RHS ) + ) >> ::
58                   Output } ; { $ LHS : ty } => { $ LHS } ;);
59
60 // test demonstrating term level `xs + ys` and type level `Expr!(Xs + Ys)`
61 fn main() {
62     fn aux<Xs: HList, Ys: HList>(xs: Xs, ys: Ys) -> Expr!(Xs + Ys) where
63      Xs: Add<Ys> {
64         xs + ys
65     }
66
67     let xs: HList!(& str , bool , Vec < u64 >) =
68         hlist!("foo" , false , vec ! [  ]);
69     let ys: HList!(u64 , [ u8 ; 3 ] , (  )) =
70         hlist!(0 , [ 0 , 1 , 2 ] , (  ));
71
72     // demonstrate recursive expansion of Expr!
73     let zs:
74             Expr!((
75                   HList ! [ & str ] + HList ! [ bool ] + HList ! [ Vec < u64 >
76                   ] ) + ( HList ! [ u64 ] + HList ! [ [ u8 ; 3 ] , (  ) ] ) +
77                   HList ! [  ]) = aux(xs, ys);
78     assert_eq!(zs , hlist ! [
79                "foo" , false , vec ! [  ] , 0 , [ 0 , 1 , 2 ] , (  ) ])
80 }