Rust has a good language feature supporting the compile-time evaluation of function.

It is const fn.

At the time this post is written this feature is not in a state of stabilized, but you can use it using Nightly Rust compiler.

An example of const fn is below.

#![feature(const_fn)]
const fn to_celsius(x: i32) -> i32 {
    ((x as f64 - 32.0) / 1.8) as i32
}

const FAHR_75: i32 = 75;
const CELS_F75: i32 = to_celsius(FAHR_75);

fn main() {
    println!("75F equals {}C", CELS_F75);
}

As we can imagine, const fn functions run at compile-time, so there are no run-time costs to use this feature. It is similar to constexpr functions in C++.

If we need to define some constants which have complex expressions, it is a good chance to use it.

If we are using fixed-length objects like arrays and want to calculate the value related to the length of the array, it is also a good chance to use const fn because Rust compiler can determine value of the elements of an expression.

To use const fn, the function must be called in constants contexts and constant arguments. In other words, the values of all elements of the expressions or statements must be determined at compile-time.

It is different from macros.

macros just replace the text at compile-time, it does not calculate expression but produces some code from meta-code. But const fn calculates some expressions.

Let’s see this.

macro_rules! to_celsius (
    ($value:expr) => (
        (($value as f64 - 32.0) / 1.8) as i32
    )
);

const FAHR_75: i32 = 75;
const CELS_F75: i32 = to_celsius!(FAHR_75);

fn main() {
    println!("75F equals {}C", CELS_F75);
}

The behavior of the two codes is the same. But the steps to make the results differ.

When the macro is used, the Rust compiler produces this code first.

const FAHR_75: i32 = 75;
const CELS_F75: i32 = ((FAHR_75 as f64 - 32.0) / 1.8) as i32;

fn main() {
    println!("75F equals {}C", CELS_F75);
}

Then Rust compiler tries to calculate the CELS_F75. In this case, the running costs of the above two programs are the same. But as you can see, using const fn makes simpler and prettier code.

Thanks for reading.