Will a const function run at runtime?

I got a const function as below:

pub const fn test(tail: u32, head: u64) -> u64 {
    let a = tail as u64;
    let shift = 64 - a.leading_zeros();
    (head << shift) | a
}

And I found that I set a break point into it and it actually stopped, so I got some questions:

  1. Is this a real const function as I expected?
  2. Can a const function also runs at runtime (like C++)?
  3. Can leading_zeros run on compile time? If not, why the compiler didn't warn me that?
  4. Any way to enforce a const function to run at compile time?

Yes, const fn acts like C++'s constexpr function in some cases.
You can force to call to happen at compiletime by assigning the result to a const or using it in a const context.

There's also an experimental called inline const.

leading_zeros is indeed const, otherwise the compiler would have given you an error.

1 Like

Generally, the const keyword has no effect on code generation when the function is used outside of a const context.

2 Likes

I got some problems here:

pub fn foo<const tail: u32, const head: u64>() -> u64 {
    const I: u64 = test(tail, head);
    return I;
}

pub fn bar(tail: u32, head: u64) -> u64 {
    const I: u64 = test(tail, head);
    return I;
}

when I use the function foo, the compiler report me that:

error[E0401]: can't use generic parameters from outer function
 --> src/main.rs:8:25
  |
7 | pub fn foo<const tail: u32, const head: u64>() -> u64 {
  |                  ---- const parameter from outer function
8 |     const I: u64 = test(tail, head);
  |                         ^^^^ use of generic parameter from outer function

and if I use bar:

error[E0435]: attempt to use a non-constant value in a constant
  --> src/main.rs:13:25
   |
13 |     const I: u64 = test(tail, head);
   |     -------             ^^^^ non-constant value
   |     |
   |     help: consider using `let` instead of `const`: `let I`

I don't find any pattern that mark a parameter as a const.

Your bar function definitely wont be possible to get to work. The value of tail and head are not guaranteed to be constant. You can get foo to compile like this:

pub fn foo<const TAIL: u32, const HEAD: u64>() -> u64 {
    struct Helper<const TAIL: u32, const HEAD: u64> {}

    impl<const TAIL: u32, const HEAD: u64> Helper<TAIL, HEAD> {
        const OUTPUT: u64 = test(TAIL, HEAD);
    }

    return Helper::<TAIL, HEAD>::OUTPUT;
}

I do not know whether there is a better way.

1 Like

Lucky enough I can just change pub const fn test(tail: u32, head: u64) -> u64 to pub const fn test2<const tail: u32, const head: u64>() -> u64 for simplicity.

But I don't figure out why const parameters are also not allowed to inherit into inner functions.

Your foo function error is merely a limitation in the compiler.

Yeah, but why? Constant is not like types, I didn't figure out the reason why constant cannot be inherit into inner functions.

Actually, const generics are treated similarly generic types in the compiler.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.