3

The Rust file examples don't appear compile with Rust 1.18.0.

For example:

use std::fs::File;
use std::io::prelude::*;
fn main() {
    let mut file = File::open("foo.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    assert_eq!(contents, "Hello, world!");
}

Error log:

rustc 1.18.0 (03fc9d622 2017-06-06)
error[E0277]: the trait bound `(): std::ops::Carrier` is not satisfied
 --> <anon>:4:20
  |
4 |     let mut file = File::open("foo.txt")?;
  |                    ----------------------
  |                    |
  |                    the trait `std::ops::Carrier` is not implemented for `()`
  |                    in this macro invocation
  |
  = note: required by `std::ops::Carrier::from_error`

error[E0277]: the trait bound `(): std::ops::Carrier` is not satisfied
 --> <anon>:6:5
  |
6 |     file.read_to_string(&mut contents)?;
  |     -----------------------------------
  |     |
  |     the trait `std::ops::Carrier` is not implemented for `()`
  |     in this macro invocation
  |
  = note: required by `std::ops::Carrier::from_error`

error: aborting due to 2 previous errors
Stargateur
  • 24,473
  • 8
  • 65
  • 91
alexbirkett
  • 2,604
  • 2
  • 26
  • 30
  • 2
    I upvoted. IMO, this is not a stupid question, since the `?` operator is a little cryptic, and it is counter intuitive that the code example cannot be put in a `main`. If I well remember, there is a RFC for permitting to use `Result` in a main. – Boiethios Jun 21 '17 at 07:28
  • 1
    For me the error log is confuse so upvote too. – Stargateur Jun 21 '17 at 07:38
  • Relevant answer: https://stackoverflow.com/a/43395610/1233251 – E_net4 Jun 21 '17 at 09:25

2 Answers2

7

? is a syntactic sugar that checks a Result: if the result is Err, it is returned as if. If there is no error (aka Ok), the function continue. When you type this:

fn main() {
    use std::fs::File;

    let _ = File::open("foo.txt")?;
}

that means:

fn main() {
    use std::fs::File;

    let _ = match File::open("foo.txt") {
        Err(e)  => return Err(e),
        Ok(val) => val,
    };
}

Then you understand that for now, you cannot use ? in the main, because main returns unit () and not Result. If you want this stuff to work, you can put it in a function that returns a Result and check it from main:

fn my_stuff() -> std::io::Result<()> {
    use std::fs::File;
    use std::io::prelude::*;

    let mut file = File::open("foo.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    // do whatever you want with `contents`
    Ok(())
}


fn main() {
    if let Err(_) = my_stuff() {
        // manage your error
    }
}

PS: There is a proposition to make work ? in the main.

Boiethios
  • 38,438
  • 19
  • 134
  • 183
4

They do compile. They just don't compile in a main function like that. If you look at the examples, they all have a big "Run" button on them. Click that and it opens the full, unabridged example on the playpen.

The one you've used above expands to this code:

fn main() {
    use std::fs::File;
    use std::io::prelude::*;

    fn foo() -> std::io::Result<()> {
        let mut file = File::open("foo.txt")?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        assert_eq!(contents, "Hello, world!");
        Ok(())
    }
}

That code doesn't compile because you've put code that propagates a Result into a function (main in this case) that doesn't return a Result.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
DK.
  • 55,277
  • 5
  • 189
  • 162
  • I saw the run button and noted the code was different. My first thought was that one or other versions was out-of-date. I suspected also that it had something to do with the `?` but being brand new to rust I did not know what `?` did. – alexbirkett Jun 21 '17 at 08:53