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
//! 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
///
/// # 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
/// }
/// }
/// ```
///
/// - 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
/// }
/// }
/// }
/// ```
///
/// [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.