DEV Community

Frederick Ollinger
Frederick Ollinger

Posted on

Rust ^ cannot use the `?` operator in a function that returns `()`

Problem:

When I try to run code with the following function:

fn invalid_function() {
    let mut file = File::open("data/AA.csv")?;
}
Enter fullscreen mode Exit fullscreen mode

This returns the following error:

$ cargo run

   Compiling voxide v0.1.0 (/rick/follinge-2020-08-10/projects/voxide)
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
  --> src/main.rs:10:45
   |
9  | fn invalid_function() {
   | --------------------- this function should return `Result` or `Option` to accept `?`
10 |     let mut file = File::open("data/AA.csv")?;
   |                                             ^ cannot use the `?` operator in a function that returns `()`
   |
   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `voxide` due to previous error
Enter fullscreen mode Exit fullscreen mode

The 1st clue is in asking ourselves what does the question mark do in this context? The answer is error propagation:

https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html

So basically it worked in main() because that was the top level function, and if we failed, we crashed as the error state was uncaught which is okay.

But if we use the question mark operator in a function, we need to return the Result which tells the caller that they need to handle a potential error state.

A better way to handle it is to either use the if or match keywords.


fn valid_function() -> () {
    if let Ok(file) = File::open("data/AA.csv") {
        // Do something with the file
    }
    else {
        // Handle the error
    }
}
Enter fullscreen mode Exit fullscreen mode

This will open a file, and check for errors.

This pattern is used so often that Rust has a match keyword for dealing with enums:

fn better_valid_function() -> () {
    let file_result = File::open("data/AA.csv");
    let file = match file_result {
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {:?}", error),
    };
}
Enter fullscreen mode Exit fullscreen mode

https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html

Top comments (0)