12 个版本
0.2.8 | 2023 年 4 月 30 日 |
---|---|
0.2.7 | 2022 年 11 月 28 日 |
0.2.6 | 2022 年 10 月 10 日 |
0.2.4 | 2022 年 7 月 6 日 |
0.2.1 | 2021 年 11 月 20 日 |
#4 in 无标准库
340,501 每月下载量
在 848 个 Crates 中使用 (16 直接)
220KB
4K SLoC
用于 const 上下文中的带格式化 panic。
由于 Rust 1.57.0 中 panic 宏在 const 上下文中的稳定性得到了保证,但缺乏格式化支持,因此存在这个库。
所有实现了 PanicFmt
特质的类型都可以在 panic 中进行格式化。
示例
基本
use const_panic::concat_assert;
const FOO: u32 = 10;
const BAR: u32 = 0;
const _: () = assert_non_zero(FOO, BAR);
#[track_caller]
const fn assert_non_zero(foo: u32, bar: u32) {
concat_assert!{
foo != 0 && bar != 0,
"\nneither foo nor bar can be zero!\nfoo: ", foo, "\nbar: ", bar
}
}
上述代码会因为这个错误而无法编译
error[E0080]: evaluation of constant value failed
--> src/lib.rs:20:15
|
8 | const _: () = assert_non_zero(FOO, BAR);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
neither foo nor bar can be zero!
foo: 10
bar: 0', src/lib.rs:8:15
在运行时调用时
use const_panic::concat_assert;
assert_non_zero(10, 0);
#[track_caller]
const fn assert_non_zero(foo: u32, bar: u32) {
concat_assert!{
foo != 0 && bar != 0,
"\nneither foo nor bar can be zero!\nfoo: ", foo, "\nbar: ", bar
}
}
将打印出这个
thread 'main' panicked at '
neither foo nor bar can be zero!
foo: 10
bar: 0', src/lib.rs:6:1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
自定义类型
自定义类型的 panic 格式化可以按照以下方式(按详尽程度递增)完成
- 使用
PanicFmt
derive 宏(需要启用 opt-in"derive"
功能) - 使用
impl_panicfmt
宏(需要启用默认启用的"non_basic"
功能) - 使用
flatten_panicvals
宏(需要启用默认启用的"non_basic"
功能) - 按照其文档中的描述手动实现
PanicFmt
特质。
此示例使用 PanicFmt
derive 方法。
use const_panic::{PanicFmt, concat_panic};
const LAST: u8 = {
Foo{
x: &[],
y: Bar(false, true),
z: Qux::Left(23),
}.pop().1
};
impl Foo<'_> {
/// Pops the last element
///
/// # Panics
///
/// Panics if `self.x` is empty
#[track_caller]
const fn pop(mut self) -> (Self, u8) {
if let [rem @ .., last] = self.x {
self.x = rem;
(self, *last)
} else {
concat_panic!(
"\nexpected a non-empty Foo, found: \n",
// uses alternative Debug formatting for `self`,
// otherwise this would use regular Debug formatting.
alt_debug: self
)
}
}
}
#[derive(PanicFmt)]
struct Foo<'a> {
x: &'a [u8],
y: Bar,
z: Qux,
}
#[derive(PanicFmt)]
struct Bar(bool, bool);
#[derive(PanicFmt)]
enum Qux {
Up,
Down { x: u32, y: u32 },
Left(u64),
}
上述代码会因为这个错误而无法编译
error[E0080]: evaluation of constant value failed
--> src/lib.rs:57:5
|
7 | / Foo{
8 | | x: &[],
9 | | y: Bar(false, true),
10 | | z: Qux::Left(23),
11 | | }.pop().1
| |___________^ the evaluated program panicked at '
expected a non-empty Foo, found:
Foo {
x: [],
y: Bar(
false,
true,
),
z: Left(
23,
),
}', src/lib.rs:11:7
限制
格式化/panic 宏的参数必须具有完全推断的具体类型,因为 const_panic
宏使用鸭子类型来调用这些参数的方法。
该限制的一个影响是,当这些整数没有被推断为具体类型时,您将不得不传递带有后缀的整数字面量(例如:100u8
)。
Panic 消息长度
panic 消息的长度只能达到 MAX_PANIC_MSG_LEN
,超过这个长度会被截断。
Cargo 功能
"non_basic"
(默认启用):启用对结构体、枚举和数组的格式化支持。
如果没有这个特性,你只能有效地格式化原始类型(自定义类型可以手动实现更困难的格式化)。
-
"rust_1_64"
(默认禁用):启用对需要Rust 1.64.0才能格式化的额外项的格式化。 -
"derive"
(默认禁用):启用PanicFmt
derive 宏。
计划
目前没有
No-std 支持
const_panic
是 #![no_std]
,可以在Rust可以使用的任何地方使用。
最低支持的 Rust 版本
这需要 Rust 1.57.0,因为它在const上下文中使用了 panic
宏。
依赖项
~0–305KB