Generic implementation specialized by const checker

struct Foo<V, T> { ... }
const fn checker<A, B>() -> bool { ... }

Foo is a generic structure and checker is a const function to do some checking.

Now I want to implement some methods for Foo like this: (The following code is not valid rust and won't compile.)

impl<V, T, U> Foo<V, T>
where
	checker::<T, U>(): true
{
    fn bar() -> ...
}

impl<V, T, U> Foo<V, T>
where
	checker::<T, U>(): false
{
    fn bar() -> ...
}

Is it possible to implement in stable rust? If the feature is still nightly, how's it going?

Stable workaround is preferred.

If there's a nightly feature for something like this, I don't know it. I also wouldn't know how to name something like this. The combination of calling a const fn and matching the result against a pattern in a where-clause seems quite far-fetched from the current capabilities of bound checks[1]. But you could head over to the Unstable Book and see if you can find something.


  1. Your proposal looks more like LISPian sorcery to me :slightly_smiling_face: ↩ī¸Ž

That's not the target syntax I'm looking for, it's just for ease of understanding. I don't care about the syntax of the implementation; I just need to make the compiler understand my bound.

The closest thing is probably this:

struct Boolean<const B: bool>;
trait True {}
impl True for Boolean<true> {}

impl<V, T, U> Foo<V, T>
where
	Boolean<{ checker::<T, U>() }>: True
{
...
}

but it doesn't work

error: generic parameters may not be used in const operations
  --> src/lib.rs:12:22
   |
12 |     Boolean<{ checker::<T, U>() }>: True
   |                         ^ cannot perform const operation using `T`
   |
   = note: type parameters may not be used in const expressions

error: generic parameters may not be used in const operations
  --> src/lib.rs:12:25
   |
12 |     Boolean<{ checker::<T, U>() }>: True
   |                            ^ cannot perform const operation using `U`
   |
   = note: type parameters may not be used in const expressions
1 Like

Maybe the generic_const_exprs can solve this. But it doesn't look like there's much hope of stabilising this feature anytime soon.

Stable workaround is preferred.

Which part of

fn bar() {
  if const { checker::<T, U>() == true } {
     // impl A
  } else {
     // impl B
  }
}

do you want to avoid?

Inline const is not stable now.

Edit:
I tried using inline constant expressions, but rustc doesn't provide static type hints for that, for example:

#![feature(inline_const)]

fn bar() -> Option<u32> {
    if const { false == true } {
        Some(10)
    } else {
        None
    }
}

fn main() {
    let b = bar();
    b.unwrap();
}

will throw an error at runtime, not compile time, which means that the const is to some extent meaningless.

Edit:

My mistake, unwrap doesn't default to const.

Using a const fn checker that panics can let the compiler understand me, and the only downside is that the error message is a little complicated and hard to understand.

Rust Playground

It's not meaningless, it just doesn't do what you want it to do.

You really want templates here, not generics and two closest things to templates that Rust offers are:

  1. Macros (but then you need to explicitly instantiate everything for all types of the interest).
  2. Associated const.

#2 is a bit closer to what you may achive in C++14 (or below) because you may play various tricks with consts. Like this, e.g.

But yeah, it's far cry from flexibility of C++17 or Zig.