fn foo() -> Result<()> throws “expected 2 type

2020-05-27 04:49发布

Why isn't Result<()> allowed when compiling this bit of Rust code? Is it a breaking change between Rust editions?

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(())
}

The compiler says:

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

When I tweak the return type to Result<(), Err>, it says:

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

This is from the wifi-connect project.

2条回答
爷、活的狠高调
2楼-- · 2020-05-27 05:14

The definition of Result is, and has always been, the following:

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

This definition is even presented in the Rust Programming language, to show how simple it is. As a generic sum type of an OK outcome and an error outcome, it always expects two type parameters, and the compiler will complain if it cannot infer them, or the list of type arguments does not have the expected length.

On the other hand, one may find many libraries and respective docs showing a Result with a single type argument, as in Result<()>. What gives?

It's still no magic. By convention, libraries create type aliases for result types at the level of a crate or module. This works pretty well because it is common for those to produce errors of the same, locally created type.

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

In fact, it is so common that the crate error-chain, one of the many error type helper crates, automatically creates this definition when using the error_chain! macro. As such, if you are in a project using error-chain (such as wifi-connect), or using a library that may or may not use error-chain, you are expected to assume that mentions of Result<T> are local type aliases to a domain-specific Result<T, Error>. In case of doubt, clicking on that type in the generated documentation pages will direct you to the concrete definition (in this case, the alias).

查看更多
我命由我不由天
3楼-- · 2020-05-27 05:22

From The Rust Programming Language section 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(())
}
查看更多
登录 后发表回答