Rust reuse const generic function at runtime

Consider I have a const generic function. I also want my users to be able to have access to a runtime variant of the function.

Consider the following snippet. Assume that N will always be in the range (0, 9).

fn digitproc_const <const N: usize> () {
    println!("{}", N);
}

fn digitproc_dyn (n: usize) {
    match n {
        0 => digitproc_const::<0> (),
        1 => digitproc_const::<1> (),
        2 => digitproc_const::<2> (),
        // Let's just assume I wrote the rest
        _ => println!("digit cannot be more than 9"),
    }
}

fn main() {
    digitproc_const::<2> ();
    digitproc_dyn(2);
}

Is there a better way of writing digitproc_dyn so that it reuses digitproc_const?

Can I express requirement that N is < 10 as a compile time constraint?

Can I somehow have one single function that can either take a const generic type or a runtime type ?

In this case, wouldn't it be better to write a regular const fn with a value argument?

const fn digitproc(n: usize) {
    â€Ļ
}

(I'm assuming you aren't actually trying to print the digit.)

I was not familiar with const functions and just read upon them. From what I understand, they are only useful in a const context ?

I will be creating arrays etc. with size n and do some heavy processing. I was under the impression that using const generics to turn n into a compile time constant would give some performance benefit.

So my thought process was if someone did digitproc_const::<2>() they would get some speedup, but at the same time, they should get the same answer (even if reduced performance) with digitproc_dyn(2). I could just copy paste the code into two functions, but I was hoping to avoid that.

What does const fn actually do here?

Const generics monomorph over each value, so you would have ten digit_proc::<_> functions in your binary (assuming the compiler determines it could called with 0..10 and nothing else). As a compile time transformation, the const parameter value must be known at compile time. More optimizations are available at the function level since the value is a constant in each monomorphized function. [1]

const fn are functions which can be evaluated at compile time in addition to being compiled and callable at runtime. If you need to calculate a constant parameter, for example, you can't use a non-const function to do so, because the parameter must be known at compile time. They're still useful at runtime, they're just also available at compile time.

If you want to call a const generic function where the const parameter is determined by a dynamic, runtime value, you will need some sort of match or other way to translate to compile-time known values. For your 0..10 example, I'd suggest some sort of enum to make it infallible.

If you're only going to call the functions in question with literal values, you don't need the dynamic version.

If you're going to be needing to support a whole lot of values, consider some other approach -- either no const generics, or only support powers of two, etc.


  1. Whether those translate into savings at the program level or not is use-case specific. If your program contains 2**30 functions, it might not be the fastest. ↩ī¸Ž

1 Like

No, that's exactly the point. You can call a const fn at runtime and it'll behave like a normal function. (If you think about it, it wouldn't make sense not to allow this – if something is simple enough that you can compute it at compile time, then surely you can also compute it at runtime.)

1 Like