Skip to main content

tailcall

Attribute Macro tailcall 

Source
#[tailcall]
Expand description

Transforms a function definition so that all recursive calls within the body are guaranteed to use a single stack frame (via tail recursion).

§Example

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.
use tailcall::tailcall;
   
#[tailcall]
fn factorial(input: u64) -> u64 {
    if input > 0 {
        input * tailcall::call! { factorial(input - 1) }
//      ^^^^^^^ This is not allowed.
    } else {
        1
    }
}
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:
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
        }
    }
}