rfcs
rfcs copied to clipboard
Feature Request static asserts
I think asserts are a pretty common thing, especially in unsafe rust (checking sizes/alignments etc.)
Now with anonymous consts we can already do things like:
use std::mem::*;
#[macro_export]
macro_rules! static_assert {
($condition:expr) => {
const _: &() = &[()][1 - ($condition) as usize];
}
}
static_assert!(size_of::<usize>() == 8);
static_assert!(size_of::<*const u8>() == 8);
static_assert!(align_of::<*const u8>() >= align_of::<u128>());
static_assert!(5>3);
I propose to add macros like this to the core library, with the whole assert
/assert_eq
/assert_ne
facade.
I think these would be really useful
It is definitely useful! Check out the static_assertions crate, which offers similar macros for compile-time asserts. It might be worth seeing if there is anything left to explore in that crate before putting the macros into core. The Rust Internals forum is often a good place for discussions like these. cc @nvzqz
https://github.com/rust-lang/rust/blob/master/src/librustc_data_structures/macros.rs#L4
@memoryruins it looks like you're not the only one this week suggesting this: https://github.com/rust-lang/rust/pull/61347#issuecomment-520943044.
rust-lang/rust#51999 allows panicking in constants, and rust-lang/rust#49146 will allow conditionals in constants. Once rust-lang/rust#49146 is implemented you will be able to improve the error messages:
#![feature(const_fn, const_panic)]
#[doc(hidden)]
pub use core as core_;
#[macro_export]
macro_rules! static_assert {
($cond:expr) => {
$crate::static_assert!($cond, concat!("assertion failed: ", stringify!($cond)));
};
($cond:expr, $($t:tt)+) => {
#[forbid(const_err)]
const _: () = {
if !$cond {
$crate::core_::panic!($($t)+)
}
};
};
}
//static_assert!(1 + 1 == 3); // not actually possible yet
The error messages are noisy but more descriptive than an integer overflow error:
error: any use of this value will cause an error
--> src/lib.rs:22:1
|
14 | / const _: () = {
15 | | //if !$cond {
16 | | $crate::core_::panic!($($t)+)
17 | | //}
18 | | };
| |__________-
...
22 | static_assert!(1 + 1 == 3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the evaluated program panicked at 'assertion failed: 1 + 1 == 3', src/lib.rs:22:1
| in this macro invocation
|
note: lint level defined here
--> src/lib.rs:13:18
|
13 | #[forbid(const_err)]
| ^^^^^^^^^
...
22 | static_assert!(1 + 1 == 3);
| --------------------------- in this macro invocation
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Evaluation in a const context works for assert
already since 1.57.0: https://github.com/rust-lang/rust/pull/89508/