为什么编译这段Rust代码时不允许使用Result<()>
?这是Rust版本之间的重大变化吗?
fn run() -> Result<()> {
let (tx, rx) = channel();
thread::spawn(move || {
do_things_with_tx(&exit_tx);
});
match exit_rx.recv() {
Ok(result) => if let Err(reason) = result {
return Err(reason);
},
Err(e) => {
return Err(e.into());
},
}
Ok(())
}
编译说:
error[E0107]: wrong number of type arguments: expected 2, found 1
--> src/main.rs:1000:18
|
1000 | fn run_wifi() -> Result<()> {
| ^^^^^^^^^^ expected 2 type arguments
当我将返回类型调整为Result<(), Err>
时,它说:
error[E0107]: wrong number of type arguments: expected 2, found 0
--> src/main.rs:1000:29
|
1000 | fn run() -> Result<(), Err> {
| ^^^ expected 2 type arguments
这是来自wifi-connect project。将在早上跟进可重现的MVCE。
Result
的定义一直是,并且一直如下:
pub enum Result<T, E> {
Ok(T),
Err(E),
}
这个定义甚至在the Rust Programming language中呈现,以显示它是多么简单。作为OK结果和错误结果的通用和类型,它总是需要两个类型参数,并且编译器会抱怨它无法推断它们或者类型参数列表没有预期的长度。
另一方面,人们可能会发现许多库和相应的文档显示带有单一类型参数的Result
,如Result<()>
。是什么赋予了?
它仍然没有魔力。按照惯例,库在包或级别的级别为结果类型创建类型别名。这非常有效,因为那些产生相同的本地创建类型的错误是很常见的。
pub type Result<T> = Result<T, Error>;
实际上,当使用error-chain
宏时,crate error_chain!
(许多错误类型帮助程序包之一)会自动创建此定义,这是很常见的。因此,如果您正在使用error-chain
(such as wifi-connect
)或使用可能使用或不使用error-chain
的库的项目中,您应该假设提及Result<T>
是特定于域的Result<T, Error>
的本地类型别名。如有疑问,在生成的文档页面中单击该类型将引导您进入具体定义(在本例中为别名)。
来自The Rust Programming Language部分The ? Operator Can Only Be Used in Functions That Return Result
use std::error::Error;
use std::fs::File;
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("hello.txt")?;
Ok(())
}