3个版本
新增 0.1.2 | 2024年8月24日 |
---|---|
0.1.1 | 2024年6月7日 |
0.1.0 | 2024年5月2日 |
在进程宏中排名第932
每月下载量200次
用于non_empty_continuous
20KB
120 行
由于Rust 1.79的发布,该crate已经过时,因为1.79添加了内联const
表达式
fn foo<const N: usize>() {
const { assert!(N > 30); }
}
其他版本尚未撤回,因为它们仍然按预期工作。
许可证:0BSD
lib.rs
:
在编译时断言语句的功能,包括使用const和类型泛型的语句。
它通过尝试评估一个常量并失败(通过编译时恐慌)来实现,如果表达式评估为假。由于cargo check
不评估常量,因此带有指定泛型的static_assert!
不会显示为错误,并且需要完整的cargo build
编译。这是一种相当“黑客式”的断言方法,因此我不太惊讶如果Rust的将来版本会破坏它。目前,它仍然在1.77.2版本中正常工作。
已经在static_assert
crate中尝试添加const泛型功能,但似乎不会很快添加。
这些断言在任何函数签名或类型系统中都没有出现,这可能使得在创建任何类型的抽象时难以推理。您可能需要谨慎使用,并在使用时明确记录。
概述
静态断言根据泛型的值有条件地引发错误
fn foo<const N: usize>() {
static_assert!((N: usize) N != 0 => "N must be a non-zero value!");
// Some other functionality.
}
fn main() {
foo::<12>(); // compiles
foo::<0>(); // doesn't compile
}
// error[E0080]: evaluation of `foo::Assert::<0>::CHECK` failed
// | static_assert!((N: usize) N != 0 => "N must be a non-zero value!");
// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'N must be a non-zero value!'
//
// note: the above error was encountered while instantiating `fn main::foo::<0>`
// | foo::<0>();
重要#1
静态断言失败(例如,在这种情况下 foo::<0>()
)在使用 cargo check
时不会显示错误。然而,尝试编译(使用 cargo build
)仍然会显示错误,这是预期的。
重要 #2
未指定泛型常量的类型将导致 can't use generic parameters from outer item
错误
fn foo<const N: u32>() {
static_assert!((N) N != 0 => "N must be a non-zero value!");
// can't use generic parameters from outer item
}
这不是宏出问题,这只是错误信息误导。可以通过简单地指定类型(static_assert!((N: u32) N != 0)
)来修复。
重要 #3
未在表达式中声明泛型将导致错误。
fn bar<const N: usize>() {
static_assert!(() N != 0 => "N must be a non-zero value!");
// can't use generic parameters from outer item
}
重要 #4
如果传递了一个 ?Sized
的类型泛型,则会导致错误
fn foo<T: ?Sized>() {
static_assert!((T) ...);
// the associated item `CHECK` exists for struct `Assert<T>`, but its trait bounds were not satisfied
}
必须使用 ?
(static_assert!((T?) ...);
)来指定可选大小泛型。
示例
断言常量表达式
static_assert!(() 1 + 2 < 17); // True statement, compiles.
static_assert!(() 45 * 25 < 3); // False statement, does not compile:
// error[E0080]: evaluation of constant value failed
// | static_assert!(() 45 * 25 < 3)
// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Static assert failed.'
可以可选地指定错误信息
static_assert!(() 45 * 25 < 3 => "This is the error message!");
// the evaluated program panicked at 'This is the error message!'
使用 identifier: type
语法传递泛型常量
fn foo<const C: u32>() {
static_assert!((C: u32) C > 3 => "C must be greater than 3!");
}
也可以使用类型泛型。
fn baz<T>() {
static_assert!((T) std::mem::size_of::<T>() == 4 => "T must be 4 bytes long!");
}
需要使用此语法传递无尺寸类型
fn baz<U: ?Sized>() {
static_assert!((U?) true => "There isn't much you can statically check about unsized types.");
}
可以同时使用多个泛型。
fn baz<const N: usize, const M: usize, T>() {
static_assert!((N: usize, M: usize) N > M => "N must be greater than M!");
static_assert!((N: usize, T) N == std::mem::size_of::<T>() / 2 => "N must be half the size of T!");
}
baz::<4, 7, u64>(); // panics at "N must be greater than M!"
baz::<4, 1, u8>(); // panics at "N must be half the size_of T!"
依赖项
~270–720KB
~17K SLoC