1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
macro_rules! coalesce_ {
($i:ident: $($v:ident: $t:ident),*) => {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum $i<$($t),*> {
$($v($t)),*
}
impl<$($t),*> $i<$($t),*> {
pub fn as_ref(&self) -> $i<$(&$t),*> {
match *self {
$(
$i::$v(ref v) => $i::$v(v)
),*
}
}
pub fn as_mut(&mut self) -> $i<$(&mut $t),*> {
match *self {
$(
$i::$v(ref mut v) => $i::$v(v)
),*
}
}
}
};
}
coalesce_!(Coalesce0: );
coalesce_!(Coalesce1: A:A);
coalesce_!(Coalesce2: A:A, B:B);
coalesce_!(Coalesce3: A:A, B:B, C:C);
coalesce_!(Coalesce4: A:A, B:B, C:C, D:D);
coalesce_!(Coalesce5: A:A, B:B, C:C, D:D, E:E);
coalesce_!(Coalesce6: A:A, B:B, C:C, D:D, E:E, F:F);
coalesce_!(Coalesce7: A:A, B:B, C:C, D:D, E:E, F:F, G:G);
coalesce_!(Coalesce8: A:A, B:B, C:C, D:D, E:E, F:F, G:G, H:H);
coalesce_!(Coalesce9: A:A, B:B, C:C, D:D, E:E, F:F, G:G, H:H, I:I);
#[macro_export]
macro_rules! coalesce {
(:&mut $i:expr; $t:ident $id:ident $x:expr => $($v:ident)*) => {
match $i {
$($crate::$t::$v(ref mut v) => { let $id = v; $x }),*
}
};
(:&$i:expr; $t:ident $id:ident $x:expr => $($v:ident)*) => {
match $i {
$($crate::$t::$v(ref v) => { let $id = v; $x }),*
}
};
(:$i:expr; $t:ident $id:ident $x:expr => $($v:ident)*) => {
match $i {
$($crate::$t::$v(v) => { let $id = v; $x }),*
}
};
(0 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce0 $id $x => ) };
(1 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce1 $id $x => A) };
(2 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce2 $id $x => A B) };
(3 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce3 $id $x => A B C) };
(4 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce4 $id $x => A B C D) };
(5 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce5 $id $x => A B C D E) };
(6 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce6 $id $x => A B C D E F) };
(7 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce7 $id $x => A B C D E F G) };
(8 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce8 $id $x => A B C D E F G H) };
(9 => |ref mut $id:ident| $x:expr) => { coalesce!(:&mut $id; Coalesce9 $id $x => A B C D E F G H I) };
(0 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce0 $id $x => ) };
(1 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce1 $id $x => A) };
(2 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce2 $id $x => A B) };
(3 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce3 $id $x => A B C) };
(4 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce4 $id $x => A B C D) };
(5 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce5 $id $x => A B C D E) };
(6 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce6 $id $x => A B C D E F) };
(7 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce7 $id $x => A B C D E F G) };
(8 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce8 $id $x => A B C D E F G H) };
(9 => |ref $id:ident| $x:expr) => { coalesce!(:&$id; Coalesce9 $id $x => A B C D E F G H I) };
(0 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce0 $id $x => ) };
(1 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce1 $id $x => A) };
(2 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce2 $id $x => A B) };
(3 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce3 $id $x => A B C) };
(4 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce4 $id $x => A B C D) };
(5 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce5 $id $x => A B C D E) };
(6 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce6 $id $x => A B C D E F) };
(7 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce7 $id $x => A B C D E F G) };
(8 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce8 $id $x => A B C D E F G H) };
(9 => |$id:ident| $x:expr) => { coalesce!(:$id; Coalesce9 $id $x => A B C D E F G H I) };
}
#[test]
fn test() {
trait T { }
struct S1; struct S2; struct S3;
impl T for S1 { } impl T for S2 { } impl T for S3 { }
let v = match 3 {
0 => Coalesce3::A(S1),
1 => Coalesce3::B(S2),
_ => Coalesce3::C(S3),
};
fn assert_t(_: &T) { }
assert_t(coalesce!(3 => |ref v| v as &_));
let v = if false { Coalesce2::A(0u16) } else { Coalesce2::B(0u32) };
assert_eq!(1u64, coalesce!(2 => |v| (v + 1) as u64));
}