How do I fix the error "type annotations needed" when creating a closure that uses the try operator?

You have to specify the return type:

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

There is a problem with the closure. You cannot name the type of a closure; you could try to reduce it to a FnOnce / FnMut, but you still would have to give it the return type.

To overcome your situation, you can specify a Result as a 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(())
}

The compiler is unable to infer the return type of the closure.

Returning Ok(()) at the end lets the compiler infer what the type of a successful result is, but not what the error type would be. The return type of the ? operator does include the full concrete type but it's guarantee is that this type can be converted into whatever the the surrounding function returns. So we need to fix that return type so all of the elided type annotations can be inferred.

Tyfingr's answer fixes the problem by removing the ?, so that the return type of the closure is the same as the return type of File::create(tmp).

hellow's answer adds an annotation on the closure so that the compiler doesn't need to infer the type.

A third fix would be to put the type annotation on the return value:

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

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

Which is similar to hellow's edit, to put the type in the return value of main().

In general, you should use a Result, and the compiler will warn you if you don't. When you handle the error, you are very likely to inadvertently provide the compiler with enough type information that none of these annotations are necessary.