Rust Recursion


Example

A macro can call itself, like a function recursion:

macro_rules! sum {
    ($base:expr) => { $base };
    ($a:expr, $($rest:expr),+) => { $a + sum!($($rest),+) };
}

Let's go though the expansion of sum!(1, 2, 3):

   sum!(1, 2, 3)
//      ^  ^~~~
//     $a  $rest
=> 1 + sum!(2, 3)
//          ^  ^
//         $a  $rest
=> 1 + (2 + sum!(3))
//               ^
//               $base
=> 1 + (2 + (3))

Recursion limit

When the compiler is expanding macros too deeply, it will give up. By default the compiler will fail after expanding macros to 64 levels deep, so e.g. the following expansion will cause failure:

sum!(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)

// error: recursion limit reached while expanding the macro `sum`
//  --> <anon>:3:46
// 3 |>         ($a:expr, $($rest:expr),+) => { $a + sum!($($rest),+) };
//   |>                                              ^^^^^^^^^^^^^^^^

When a recursion limit is reached, you should consider refactoring your macro, e.g.

  • Maybe recursion could be replaced by repetition?
  • Maybe the input format could be changed to something less fancy, so we don't need recursion to match it?

If there is any legitimate reason 64 levels is not enough, you could always increase the limit of the crate invoking the macro with the attribute:

#![recursion_limit="128"]
//                  ^~~ set the recursion limit to 128 levels deep.