[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <DGA6C99D24FV.34J2JWKWY08LS@garyguo.net>
Date: Mon, 09 Feb 2026 05:16:11 +0000
From: "Gary Guo" <gary@...yguo.net>
To: "Yury Norov" <ynorov@...dia.com>, "Miguel Ojeda"
<miguel.ojeda.sandonis@...il.com>
Cc: "Gary Guo" <gary@...yguo.net>, "Benno Lossin" <lossin@...nel.org>,
"Miguel Ojeda" <ojeda@...nel.org>, "Boqun Feng" <boqun@...nel.org>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>, "Andreas
Hindborg" <a.hindborg@...nel.org>, "Alice Ryhl" <aliceryhl@...gle.com>,
"Trevor Gross" <tmgross@...ch.edu>, "Danilo Krummrich" <dakr@...nel.org>,
"Alexandre Courbot" <acourbot@...dia.com>, "Yury Norov"
<yury.norov@...il.com>, "Nathan Chancellor" <nathan@...nel.org>, "Nicolas
Schier" <nsc@...nel.org>, <linux-kernel@...r.kernel.org>,
<rust-for-linux@...r.kernel.org>, <linux-kbuild@...r.kernel.org>
Subject: Re: [PATCH 2/2] rust: add `const_assert!` macro
On Sun Feb 8, 2026 at 9:07 PM GMT, Yury Norov wrote:
> On Sun, Feb 08, 2026 at 11:35:51AM +0100, Miguel Ojeda wrote:
>> On Sun, Feb 8, 2026 at 6:58 AM Yury Norov <ynorov@...dia.com> wrote:
>> >
>> > This is confusing. You begin with "const_assert!() is more powerful",
>> > and finally recommend to use a less powerful option.
>>
>> The goal is that users use the least powerful one that applies, not
>> the other way around, because the least powerful ones fail earlier and
>> are generally more robust.
>>
>> I think the first example is intended to show the different ones, but
>> I think the wording can be improved -- the one in the existing
>> `build_assert!` docs is a bit clearer.
>
> Can you please keep more context? It would be easier to refer to an
> example if I have it on hand.
>
>> Gary: perhaps we could factor out the explanation/examples to the
>> module-level docs, and then link to it from all the three asserts.
>>
>> > I don't think this compiler implementation details should sneak into
>> > the kernel. The compiler may get changed, or whatever else, and this
>> > all will become just non-relevant.
>>
>> How do they sneak into the kernel? Gary is explaining why it is not
>> called "link time", precisely because that would expose more details,
>> not less.
>>
>> Regardless, that "link-time" vs. "build-time" discussion is
>> independent of this patch, because those docs already exist in the
>> tree.
>
> Again, more context would help. So this is the original comment from
> Benno, and Gary's reply:
>
> > I think having "Build-time check" here is a bit confusing, how about we
> > change it to "Link-time check"? Since a "Compile-time check" also is
> > done at "Build-time"
>
> This is the intentional phrasing that I used for `build_assert!` when I created
> it, for the reason that `build_assert!` ensure that it will fire, at latest,
> link time. However, if you actually use such methods with CTFE, it will error
> earlier. So it is "at latest link-time check", so I decided to just use
> "build-time".
>
> I agree with ""Build-time check" here is a bit confusing", and the
> following indeed looks like a compiler implementation discussion. So
> I concluded that the difference between build_assert and const_assert
> is not visible from programmer's POV. Please correct me if I'm wrong.
>
>> > On the C side we've got similar statically_true() and const_true()
>> > macros, but they seemingly have a different meaning:
>>
>> > Is it possible to maintain consistency with C on rust side? If not,
>> > can you take those C comments as the reference for what level of
>> > detalization is desired? Maybe pick different names then?
>>
>> Please explain what inconsistency you are seeing here.
>
> OK, maybe it's just me, but this is how I build a map between rust and C:
>
> - Plain BUG_ON() matches plain assert!();
> - BUILD_BUG_ON() is compiletime_assert() and matches build_assert!();
These two are correct.
Notably, `build_assert!` uses the same mechanism as `BUILD_BUG_ON`, i.e.
generating a undefined symbol reference is it failed to be optimized out.
> - BUILD_BUG_ON_ZERO() - same as BUILD_BUG_ON(), but can be used in
> initialization constructions, like GENMASK(), i.e. rvalue. No direct
> analogue in Rust;
> - BUILD_BUG_ON(statically_true()) - allows runtime conditions, like
> "true || runtime_cond", and matches static_assert!() in rust;
`static_assert!(expr)` in Rust is equivalent to `static_assert(expr)` in C. This
means that the expression is evaluated by the compiler.
There's no equivalent construct of `statically_true` and `const_true` in Rust.
Rust intentionally avoid providing the ability to observe different behaviour in
compile time and runtime. These macros simply return `false` if the
evaluatability is not met; Rust's `static_assert!()` (and C's `static_assert!`
and the `const_assert!()` will fail the compilation with a compiler error (not
an assertion failure) if the expression cannot be evaluated at compile time.
> - BUILD_BUG_ON(const_true()) - doesn't allow runtime conditions.
>
> I expected that const_assert!() would be an analogue for
> BUILD_BUG_ON(const_true()), but it is seemingly a different thing. Or
> am I wrong?
>
Let me give a summary of the three assertions in Rust:
`static_assert!(expr)` is equivalent to `static_assert` in C. It requires `expr`
to be a constant expression. This expression cannot refer to any generics.
When you write a `static_assert!(expr)` in a program, it is always evaluated,
regardless if the function it appears in is used or not.
`const_assert!()` has no equivalent in C, because C does not have generics.
However, you can treat it as a more powerful version of `static_assert!()`. We
need it because it has the ability to refer to generics. It also requires the
expression to be constant expression. *However*, because it can refer to
generics, it is inherently tied to a specific instance of a function. So if you
use it in a generic function and the function is not used, the assertion will
not be performed. `static_assert!` is recommend over `const_assert!` if possible
for this reason. It also has a limitation that it is only usable inside a
function (strictly speaking in Rust term, bodies).
`build_assert!()` is equivalent to our `BUILD_BUG_ON`. It is even more powerful
than `const_assert!()` because it is supposed to be able to check tautologies
that depend on runtime value (similar to C). However, as the assertion failure
mechanism is undefined symbol and linker error, it is not developer friendly so
it is recommend to avoid it and prefer other two assertions where possible.
In summary:
`static_assert!()`, `const_assert!()` and `build_assert!()` in that order has
increasing expressiveness, but decreasing robustness and the checks are
performed later in the pipeline. Hence, the suggestion to use the least powerful
one that still works.
Regarding the name:
`const_assert!()` has it's name because it is literally
const { assert!() }
where `const {}` is a construct in Rust which says "this must be a constant
expression and evaluated at compile time". The names here refer to related Rust
constructs rather than `statically_true` and `const_true` in the C side.
Best,
Gary
>> Also, please note that two of the three names have been for years in
>> the kernel tree, and that standard C also uses `static_assert` as a
>> name. `const_assert` fits the pattern and it literally expands to what
>> it says.
>>
>> Moreover, `const` in C is not the same as `const` in Rust. `constexpr`
>> in C is closer to `const` in Rust.
>>
>> By the way, I am not sure why you suggested `const_true` for the name
>> of that C macro -- I think it should be `constexpr_true` instead,
>> which is closer to what it does, and it fits the pattern on the C side
>> better, too. So that would be more consistent.
>
> I suggested const_true() over the original underscored _statically_true(),
> and this is an obvious improvement. If you think that 'constexpr_true()'
> would add to explainability, please submit a patch. I have a weakly
> negative opinion on that.
>
> Thanks,
> Yury
Powered by blists - more mailing lists