很简单,我在一个结构体上有一个setter方法,它设置了一个i32
类型的字段值,我不想允许零或负数。我用assert!
宏实现了这一点,如下所示:
pub fn set_myfield(&mut self, arg: i32) {
assert!(arg > 0);
self.myfield = arg;
}
如果调用者调用set_myfield(0)
,但在编译时没有给出错误,这似乎会在运行时导致死机。是否有任何类型的Assert,我可以写,使我的库的消费者将得到一个错误 * 在编译时 *,如果他们的代码试图调用这个方法与零或负输入?
2条答案
按热度按时间bf1o4zei1#
在Rust中,没有办法将类型值的 * 子集 * 指定为类型。但是,您可以定义新的类型来实施规则,或者使用现有的规则,甚至有一个现有的类型用于您想要的规则:
std::num::NonZeroI32
。现在,从某种意义上说,这并没有改变任何东西--仍然需要运行时检查来构造
NonZeroI32
。然而,这意味着:set_myfield
之前进行检查,这可以简化错误处理路径。而且,在Rust的未来版本中,可能(在适用的情况下)定义非零类型的常量,使所有内容都在编译时被检查。
(现在,这段代码无法编译,因为
Option::unwrap()
在const
评估中不可用。)vshtjzan2#
我认为你正在寻找的是类似于Zig的
comptime
功能的东西。但是在Rust中,如果你试图在 * 编译时 * 防御文字
0
值,你可以使用macro_rules
和内置的compile_error!
宏。下面是一个工作示例(Rust Playground):
您可以将
Arg
移动到其自己的模块中,以防止用户直接设置其内部值。