2个版本
0.0.2 | 2023年7月21日 |
---|---|
0.0.1 | 2023年6月7日 |
#222 in 无标准库
6KB
#[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检测。这包括库crates的
cargo build
和二进制和库crates的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,并在运行时出现未定义行为,请参阅dtolnay/no-panic#16;尝试在该调用周围使用unsafe extern "C"
包装器。
致谢
链接器错误技术基于Kixunil的crate dont_panic
。查看该crate以获取其他要求无panic的便捷方式。
许可协议
根据您的选择,在Apache License, Version 2.0或MIT license下获得许可。除非您明确声明,否则您提交给此crate的任何有意贡献,根据Apache-2.0许可协议定义,应按上述方式双许可,不附加任何额外条款或条件。
依赖项
~265–710KB
~17K SLoC