2个版本
0.0.2 | 2023年7月21日 |
---|---|
0.0.1 | 2023年6月7日 |
在 #no-panic 中排名 6
用于 noexcept
7KB
130 行
#[no_panic]
一个Rust属性宏,要求编译器证明一个函数永远不会panic。
[dependencies]
no-panic = "0.1"
use no_panic::no_panic;
#[no_panic]
fn demo(s: &str) -> &str {
&s[1..]
}
fn main() {
println!("{}", demo("input string"));
}
如果函数panic了(或者编译器未能证明函数不能panic),程序将因为链接器错误而无法编译,错误信息中将包含函数名称。让我们通过传递一个无法在第一个字节处切片的字符串来触发这种情况
fn main() {
println!("{}", demo("\u{1f980}input string"));
}
Compiling no-panic-demo v0.0.1
error: linking with `cc` failed: exit code: 1
|
= note: /no-panic-demo/target/release/deps/no_panic_demo-7170785b672ae322.no_p
anic_demo1-cba7f4b666ccdbcbbf02b7348e5df1b2.rs.rcgu.o: In function `_$LT$no_pani
c_demo..demo..__NoPanic$u20$as$u20$core..ops..drop..Drop$GT$::drop::h72f8f423002
b8d9f':
no_panic_demo1-cba7f4b666ccdbcbbf02b7348e5df1b2.rs:(.text._ZN72_$LT$no
_panic_demo..demo..__NoPanic$u20$as$u20$core..ops..drop..Drop$GT$4drop17h72f8f42
3002b8d9fE+0x2): undefined reference to `
ERROR[no-panic]: detected panic in function `demo`
'
collect2: error: ld returned 1 exit status
错误信息不是很突出,但请注意错误信息末尾的ERROR[no-panic],它提供了有问题的函数名称。
注意事项
-
需要一定优化量才能证明它们不会panic的函数,在被标记为
#[no_panic]
之后可能无法在调试模式下编译。 -
panic检测在链接时在整个依赖图中发生,因此任何不调用链接器的Cargo命令都不会触发panic检测。这包括库crate的
cargo build
命令和二进制crate或库crate的cargo check
命令。 -
当代码使用
panic = "abort"
构建时,此属性无意义。
如果你发现代码需要优化才能通过 #[no_panic]
,要么将no-panic作为可选依赖项,只在你想要在发布构建中启用时才启用,要么将以下类似部分添加到你的Cargo.toml或.cargo/config.toml中,以在调试构建中启用非常基本的优化。
[profile.dev]
opt-level = 1
如果您需要证明的代码没有panic,并且调用了来自不同crate的非泛型非内联函数,您可能需要启用薄LTO,以便链接器推断这些函数不会panic。
[profile.release]
lto = "thin"
如果薄LTO不起作用,下一步尝试的应该是带有单个代码生成单元的胖LTO。
[profile.release]
lto = "fat"
codegen-units = 1
如果您想让no_panic仅假设您调用的某些函数不会panic,如果在运行时发生panic,则得到未定义行为,请参阅dtolnay/no-panic#16;尝试将此调用包裹在unsafe extern "C"
包装器中。
致谢
链接器错误技术基于Kixunil的crate dont_panic
。查看该crate以获取要求panic不存在的其他方便方法。
许可证
在您的选择下,根据Apache License, Version 2.0或MIT license进行许可。除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交的任何贡献,包括但不限于此crate,都应双许可如上所述,不附加任何其他条款或条件。
依赖项
~295–750KB
~18K SLoC