Description
Proposal
Problem statement
People often want to check some conditions at compile-time, but currently Rust does not have an intuitionistic way to do it.
Motivating examples or use cases
Here are use cases in rust-lang/rust and Rust-for-Linux:
People define their own versions of static_assert
macros to meet the requirements.
Solution sketch
Add a new macro static_assert
which check it's argument in compile-time.
static_assert
is allowed to used at module's top-level, not like assert
which can only used in a function or initialization context:
// allowed
static_assert!(0 == 0);
// not allowed: error: non-item macro in item position
assert!(0 == 0);
Like assert
and debug_assert
, static_assert_eq
and static_assert_ne
could also be added to the standard library.
The error message for failed assertion would be like:
error[E0796]: static assertion failed
--> src/lib.rs:7:1
|
7 | static_assert!(0 == 1);
| ^^^^^^^^^^^^^^^^^^^^^^^ static assertion failed: 0 == 1
The macro can take a custom error message like assert
, but currently we cannot call non-const formatting macro in constants. My opinion is just keeping the behavior same as assert
, in the future when formating is allowd in const context, we would automaticly get the feature.
The macro should be able to be used in generic context to assert about generic parameters:
fn foo<const N: usize>() {
static_assert!(N < 2);
}
Maybe some drawbacks:
- Adding macros to prelude is a break change. But the
todo
,dbg
andmatches
were added to prelude, maybe this is not a big problem? - Maybe we could use another name, such as
const_assert
. I thinkstatic_assert
is better, becaus C, C++ and rustc developers just used it.
Alternatives
There are several alternatives, the precondition is that const_panic
is stablized since Rust 1.57, so we could perform assertion at const context, which would cause a compile-time error.
We can write const _: () = assert!(condition)
. This is stable, and works for most cases. The drawback is that it is not intuitionistic with grammar noise. People need to lean them from somewhere, such as TRPL or Rust Cookbook.
Another drawback of const _: () = assert!(condition)
is that, due to E0401, you cannot assert about generic parameters:
fn foo<const N: usize>() {
const _: () = assert!(N < 1);
}
This code cannot be compiled currently, so Rust-For-Liunx has to use a build_assert
macro.
With const
block stable since 1.79, we could write const { assert!(condition) }
to perform static assertion. It has no problem with generic parameters:
#![feature(inline_const)]
pub fn foo<const N: usize>() {
const { assert!(N < 1); };
}
pub fn bar() {
foo::<0>();
// foo::<1>();
}
But the const
block has another issue: it is an expression so it is not able to be written at top level. I think it is easy to define the top-level const
block:
const {
do_sth();
}
is identical to
const _: () = {
do_sth();
};
Links and related work
- https://internals.rust-lang.org/t/idea-static-assertions/7753
- https://internals.rust-lang.org/t/nicer-static-assertions/15986
- Static asserts rfcs#1146
static_assertions
crate
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.
Second, if there's a concrete solution:
- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.