Re: [PATCH 2/2] rust: num: add `cv!` macro to create values from constant expressions
From: Alexandre Courbot
Date: Sat Aug 29 2026 - 00:05:52 EST
On Fri Aug 28, 2026 at 9:03 PM JST, Gary Guo wrote:
> Currently, constructing a `NonZero` or `Bounded` from a constant is
> verbose. The former would require `const { NonZero::new(...).unwrap() }`
> and the latter require turbofish. Similarly, the `num::casts` exposes
> methods that cast numbers using turbofish syntax, which is unergonomic and
> unnecessarily causes the value to flow into the type system, which is very
> restrictive without `generic_const_exprs`.
>
> Implement a macro `cv!` (short for constant value) which converts a const
> integer to types that implements `FromConst` trait and validate them during
> const evaluation.
>
> The usage is of form
>
> cv!(<expression>)
>
> for inferred type and
>
> cv!(<expression> => <type>)
>
> for explicit type specification.
>
> As we do not have const trait implementation yet, dark magic is used. The
> dark magic is documented in the code, but in essence it defines inherent
> `__from_const` impls on types, which can be marked const, and rely on
> Rust's method resolution algorithm to pick the correct function. Multiple
> helpers are defined to aid type inference to work properly.
>
> As a result, this allows construction of primitive integers, `NonZero`,
> `Bounded`, `Alignment` using a single `cv!` macro. This macro does not have
> `generic_const_exprs` restrictions (e.g. in a function with `const N: u32`
> generic parameter, you may use `cv!(N + 1)`), it supports full type
> inference and it has nice error messages in some common error scenario:
>
> error[E0080]: evaluation panicked: constant is zero
> --> example.rs:22:25
> |
> 22 | const X: NonZero<u32> = cv!(0);
> | ^^^^^^ evaluation of `X::{constant#0}` failed inside this call
>
> error[E0277]: `kernel::page::Page` cannot be converted from constant
> --> example.rs:22:17
> |
> 22 | const X: Page = cv!(0);
> | ^^^^^^ the trait `kernel::num::FromConst` is not implemented for `kernel::page::Page`
>
> Of course, this trick is not full const trait impl. So the following code cannot work properly:
>
> fn generic<T: FromConst>() -> T {
> cv!(0)
> }
>
> That said, useful error message is still produced in this context.
>
> error[E0080]: evaluation panicked: `cv!()` cannot be used with generic types yet
> --> example.rs:23:5
> |
> 22 | cv!(0)
> | ^^^^^^ evaluation of `generic::<u32>::{constant#0}` failed inside this call
>
> Co-developed-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
> Signed-off-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
> Signed-off-by: Gary Guo <gary@xxxxxxxxxxx>
That's cool, and I like the inherent generality of it, but OTOH I am not
sure that invoking dark magic is warranted in a world where all current
in-tree users are covered by Eliot's version (with a few hacks, granted,
but these are not visible to callers - and this version also has quite a
few hacks of its own).
I think this is a case where I'd rather live with a small limitation for
a while until the language is capable of covering what we need natively.
Or at least, until the generalized version you mentioned in your reply
becomes kernel infrastructure and we can benefit from it here for free.
Since the public interface of both versions is identical, switching from
one mechanism to the other would be transparent anyway.
Eliot is driving the series so the call is his to make, but I think we
can make something available sooner (and we need it soon) if we start
with his solution.