fn foo() -> Result<()> 抛出“预期 2 个类型参数”

问题描述 投票:0回答:4

为什么在编译这段 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 项目

error-handling rust
4个回答
50
投票

Result
的定义始终如下:

pub enum Result<T, E> {
    Ok(T),
    Err(E),
}

这个定义甚至出现在Rust 编程语言中,以显示它是多么简单。作为 OK 结果和 error 结果的通用求和类型,它始终需要两个类型参数,如果编译器无法推断它们,或者类型参数列表没有预期的长度,则会抱怨。

另一方面,人们可能会发现许多库和各自的文档显示带有单个类型参数的

Result
,如
Result<()>
中所示。给什么?

这仍然没有魔法。按照惯例,库会在板条箱或模块级别为结果类型创建类型“别名”。这非常有效,因为这些错误通常会产生相同的本地创建类型的错误。 pub type Result<T> = std::result::Result<T, Error>;

或者,仍然可以声称是原始结果类型的定义。

pub type Result<T, E = Error> = std::result::Result<T, E>;

这种模式非常常见,以至于一些错误助手包(例如 

error-chain

)会自动为每个声明的错误创建一个结果别名类型。
因此,如果您使用的库可能使用或不使用 
error-chain,则您应该假设提及
Result<T>
是特定于域的
Result<T, Error>
的本地类型别名。如有疑问,在生成的文档页面中单击该类型将引导您找到具体定义(在本例中为别名)。
    


9
投票
Rust 编程语言

部分 ?运算符只能用在返回结果的函数中 use std::error::Error; use std::fs::File; fn main() -> Result<(), Box<dyn Error>> { let f = File::open("hello.txt")?; Ok(()) }



5
投票

use std::io::Result;

链接至
类型描述

长答案

我相信

E_net4评论标记者

给出的投票最高的答案是正确的。但如果盲目应用则不起作用。在这两种情况下 这个

pub type Result<T> = Result<T, Error>;

还有这个

pub type Result<T, E = Error> = Result<T, E>;

会给出循环依赖错误

error[E0391]: cycle detected when expanding type alias `Result` --> src\main.rs:149:33 | 149 | pub type Result<T, E = Error> = Result<T, E>; | ^^^^^^^^^^^^ | = note: ...which immediately requires expanding type alias `Result` again = note: type aliases cannot be recursive = help: consider using a struct, enum, or union instead to break the cycle = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information

因此,SO 的用户不想承认这一点,但是 
Gabriel soft

非常接近优雅的解决方案,因为该类型别名 pub type Result<T> = result::Result<T, Error>;

直接来自

标准库。 在这里,我们想要的带有 1 个通用参数的

Result

std::io
(
docs
) 中定义。为了解决我添加的问题 use std::io::Result; fn some_func() -> Result<()> { ... }

use std::io; fn some_func() -> io::Result<()> { ... }

rustc 
1.62.1


0
投票
Result

类型来处理错误来解决了我自己的错误。

它需要 T 和 E 的泛型,所以为了简化事情,我这样做了:

pub type Result<T> = result::Result<T, Error>;

	
© www.soinside.com 2019 - 2024. All rights reserved.