创建使用try运算符的闭包时,如何解决错误“需要类型注释”?

时间:2018-07-23 10:38:08

标签: error-handling rust closures type-inference

use std::fs::File;

fn main() {
    let tmp = "tmp.zip";

    let save_to_tmp_file = || {
        let mut tmp_zip = File::create(tmp)?;
        Ok(())
    };

    save_to_tmp_file();
}

playground

构建错误:

error[E0282]: type annotations needed
 --> src/main.rs:7:27
  |
6 |     let save_to_tmp_file = || {
  |         ---------------- consider giving `save_to_tmp_file` a type
7 |         let mut tmp_zip = File::create(tmp)?;
  |                           ^^^^^^^^^^^^^^^^^^ cannot infer type for `_`

3 个答案:

答案 0 :(得分:2)

您必须指定返回类型:

use std::fs::File;
use std::io;

fn main() {
    let tmp = "tmp.zip";

    let save_to_tmp_file = || -> Result<(), io::Error> {
        let mut tmp_zip = File::create(tmp)?;
        Ok(())
    };

    save_to_tmp_file();
}

关闭存在问题。您无法命名闭包的类型;您可以尝试将其简化为FnOnce / FnMut,但仍必须为其提供返回类型。

要克服这种情况,您可以将Result指定为return type for your main function

use std::io;
use std::fs::File;

fn main() -> Result<(), io::Error> {
    let tmp = "tmp.zip";
    let mut tmp_zip = File::create(tmp)?;
    Ok(())
}

答案 1 :(得分:2)

编译器无法推断闭包的返回类型。

最后返回Ok(())可使编译器推断成功结果的类型,而不是错误类型。 ?运算符确实的返回类型包括完整的具体类型,但是可以保证,无论周围函数返回什么,都可以将该类型转换为。因此,我们需要修复该返回类型,以便可以推断所有被淘汰的类型注释。

Tyfingr's answer通过删除?来解决此问题,因此闭包的返回类型与File::create(tmp)的返回类型相同。

hellow's answer在闭包上添加注释,以便编译器无需推断类型。

第三种解决方法是将类型注释放在返回值上:

let save_to_tmp_file = || {
    let mut tmp_zip = File::create(tmp)?;
    Ok(())
};

let result: Result<_, io::Error> = save_to_tmp_file();

与hellow的编辑类似,将类型放入main()的返回值中。

通常,您应该使用一个Result,如果不使用,编译器会警告您。处理错误时,很可能会无意间为编译器提供了足够的类型信息,而这些注释都不是必需的。

答案 2 :(得分:1)

Rust是一种表达性的语言,因此您只需返回Result,它就可以正常工作:

use std::fs::File;

fn main() {
    let tmp = "tmp.zip";

    let save_to_tmp_file = || {
        File::create(tmp)
    };

    save_to_tmp_file().expect("Can't create a tmp file");
}

或者只是写:

fn main() {
    let tmp = "tmp.zip";
    File::create(tmp).expect("Can't create a tmp file");
}