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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! This crate contains the procedural macro implementation for the
//! <https://crates.io/crates/tailcall> crate.
//! It is not designed to be used directly.
extern crate proc_macro;
use TokenStream;
use ;
/// Transforms a [function definition] so that all recursive calls within the body are
/// guaranteed to use a single stack frame (via [tail recursion]).
///
/// [function definition]: https://docs.rs/syn/1.0.9/syn/struct.ItemFn.html
/// [tail recursion]: https://en.wikipedia.org/wiki/Tail_call
///
/// For simple free functions and inherent methods that only tail-call themselves directly, the
/// macro lowers the item into an inline `loop`. More complex cases keep the hidden
/// thunk-builder shape and run through `tailcall::runtime::Thunk`.
///
/// For methods, the optimized path aliases the receiver once, reuses the non-receiver arguments
/// as mutable loop state, and rewrites each direct self tail call into "compute the next
/// arguments, assign them, and continue".
///
/// # Example
///
/// ```ignore
/// use tailcall::tailcall;
///
/// fn factorial(input: u64) -> u64 {
/// #[tailcall]
/// fn factorial_inner(accumulator: u64, input: u64) -> u64 {
/// if input > 0 {
/// tailcall::call! { factorial_inner(accumulator * input, input - 1) }
/// } else {
/// accumulator
/// }
/// }
///
/// factorial_inner(1, input)
/// }
/// ```
///
/// # Requirements
///
/// - Tail-call sites must be written with `tailcall::call!` and left in [tail form]:
/// `tailcall::call!` currently supports direct function paths and method syntax on `self`.
///
/// ```compile_fail
/// use tailcall::tailcall;
///
/// #[tailcall]
/// fn factorial(input: u64) -> u64 {
/// if input > 0 {
/// input * tailcall::call! { factorial(input - 1) }
/// // ^^^^^^^ This is not allowed.
/// } else {
/// 1
/// }
/// }
/// ```
///
/// ```compile_fail
/// use tailcall::tailcall;
///
/// #[tailcall]
/// fn factorial(input: u64) -> u64 {
/// if input > 0 {
/// 1 + tailcall::call! { factorial(input - 1) }
/// // ^^^^^^^^^^^^^^^ This is not allowed.
/// } else {
/// 1
/// }
/// }
/// ```
///
/// - Function arguments must use simple identifier patterns:
///
/// ```compile_fail
/// use tailcall::tailcall;
///
/// #[tailcall]
/// fn sum((left, right): (u64, u64)) -> u64 {
/// // ^^^^^^^^^^^^^ Simple identifier arguments are required.
/// left + right
/// }
/// ```
///
/// - Methods in `impl` blocks are supported, but trait methods are not:
///
/// ```compile_fail
/// use tailcall::tailcall;
///
/// trait Factorialable {
/// fn factorial(self) -> Self {
/// self.calc_factorial(1)
/// }
///
/// fn calc_factorial(self, accumulator: u64) -> u64;
/// }
///
/// impl Factorialable for u64 {
/// #[tailcall]
/// fn calc_factorial(self, accumulator: u64) -> u64 {
/// // ^^^^ Trait methods are not supported yet.
/// if self > 0 {
/// (self - 1).calc_factorial(self * accumulator)
/// } else {
/// accumulator
/// }
/// }
/// }
/// ```
///
/// - `async fn` and `const fn` are not supported:
///
/// ```compile_fail
/// use tailcall::tailcall;
///
/// #[tailcall]
/// async fn countdown(input: u64) -> u64 {
/// if input > 0 {
/// tailcall::call! { countdown(input - 1) }
/// } else {
/// 0
/// }
/// }
/// ```
///
/// ```compile_fail
/// use tailcall::tailcall;
///
/// #[tailcall]
/// const fn countdown(input: u64) -> u64 {
/// if input > 0 {
/// tailcall::call! { countdown(input - 1) }
/// } else {
/// 0
/// }
/// }
/// ```
///
/// [tail form]: https://en.wikipedia.org/wiki/Tail_call
/// Marks an explicit trampoline-backed tail-call site inside a `#[tailcall]` function.
///
/// The macro expects either a direct function call or a method call on `self`, such as:
///
/// ```ignore
/// tailcall::call! { factorial_inner(acc * input, input - 1) }
/// tailcall::call! { self.is_odd(x - 1) }
/// ```
///
/// It expands to a call to the hidden trampoline builder generated by the `#[tailcall]`
/// attribute. The call site itself must remain in tail position.