web-dev-qa-db-ja.com

fn foo()-> Result <()>は「期待される2つの型の引数」をスローします

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プロジェクト からのものです。

7
Petrus Theron

Resultの定義は次のとおりです。

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

この定義は the Rustプログラミング言語 でも示され、その単純さを示しています。の一般的な合計タイプとして[〜#〜] ok [〜#〜]結果とerror結果、常に2つの型パラメーターが必要です、そしてコンパイラーはそれらを推論できない場合、または型引数のリストが予期された長さでない場合に文句を言います。

一方、Result<()>のように、単一の型引数を持つResultを示す多くのライブラリとそれぞれのドキュメントを見つけることができます。何ができますか?

それはまだ魔法ではありません。慣例により、ライブラリーはクレートまたはモジュールのレベルで結果タイプのタイプaliasesを作成します。ローカルで作成された同じタイプのエラーが発生することがよくあるため、これはかなりうまく機能します。

_pub type Result<T> = Result<T, Error>;
_

実際、非常に一般的であるので、_error-chain_マクロを使用すると、多数のエラータイプヘルパークレートの1つであるクレート _error_chain!_ がこの定義を自動的に作成します。そのため、_error-chain_( _wifi-connect_ など)を使用するプロジェクト、または_error-chain_を使用する場合と使用しない場合があるライブラリを使用している場合は、 _Result<T>_の言及は、ドメイン固有の_Result<T, Error>_へのローカルタイプエイリアスであると想定されます。疑わしい場合は、生成されたドキュメントページでそのタイプをクリックすると、具体的な定義(この場合はエイリアス)に移動します。

16

From The Rustプログラミング言語 セクション ?演算子は結果を返す関数でのみ使用できます

use std::error::Error;
use std::fs::File;

fn main() -> Result<(), Box<dyn Error>> {
    let f = File::open("hello.txt")?;

    Ok(())
}
3
E-rich