Search code examples
rustconstants

Can I make the result of `match`ing on a `const` expression be `const` too?


This code does not compile, since rustc claims that f would need to be const:

const FOO: Option<u32> = None;

fn implementation_with_const<const V: u32>() {
    println!("Got {}", V);
}

fn implementation_without_const() {
    println!("Did not get a constant");
}

fn main() {
    match FOO {
        Some(f) => implementation_with_const::<{f}>(),
        None => implementation_without_const(),
    };
}

To all appearances, f satisfies all conditions of being const. Is there some way I can rewrite my code so that what I'm trying to do is possible? (In my real application, FOO is a constant defined in a library based on information about the target machine, and the argument of implementation_with_const() does need to be statically known, so I cannot simply inline it, or turn the const parameter into a regular one.)

Using the unstable feature #![feature(const_option)] and replacing {f} with {FOO.unwrap()} causes a compile failure if FOO is None since both branches of the match are evaluated regardless of FOO.


Solution

  • It's a bit hacky and requires you to have a const way of constructing the inner type, but this should work.

    fn main() {
        const FOO_UNWRAP: u32 = if let Some(f) = FOO { f } else { 0 };
        if FOO.is_some() {
            implementation_with_const::<FOO_UNWRAP>();
        } else {
            implementation_without_const();
        }
    }