Rustの`?`クエスチョンマーク2

最近Rust 勉強中です。

Rustのクエスチョンマーク(?) - c_leaf.blog
去年もRustの?について調べた時のメモがわりの記事を書いていたのですが
うまく理解できていなかったのでもう一度調べて書き直したいと思います。

rustc 1.21.0 (3b72af97e 2017-10-09)です。

下記はtxtファイルから中身を読み込む処理です。

let mut file = File::open("./hello.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;

?が出てきています。

このままmain関数に書くとエラーが起きます。

fn main() {
    let mut file = File::open("./hello.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
}
/*
  |
  | let mut file = File::open("./hello.txt")?;
  |             ---------------------------------
  |           |
  |           the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
  |           in this macro invocation
  |
*/

? マークはResultを返す関数の中だけで使えるよ!でしょうか?

その通りでこの?マークは
関数の中でResultに対して使います。
Errが上がった場合すぐにErrをreturn、
Okが上がった場合処理を続行します。

こんな感じ

// read_file  read_file2は同じ処理
//?を使わない版
fn read_file() -> Result<String> {
    let mut file = match File::open("./hello.txt") {
        Ok(file) => file,
        Err(e) => return Err(e)
    };

    let mut contents = String::new();

    match file.read_to_string(&mut contents) {
        Ok(_) => {},
        Err(e) => return Err(e)
    }

    Ok(contents)
}

//?版
fn read_file2() -> Result<String> {
    let mut file = File::open("./hello.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

//これらを呼び出すときは
fn main() {
    // unwrapしちゃったり
    let str1 = read_file().unwrap();
    let str2 = read_file2().unwrap();

    // errorハンドリングしちゃったり
    match read_file() {
        Ok(src) => println!("{}", src),
        Err(err) => println!("{}", err)
    }
    match read_file2() {
        Ok(src) => println!("{}", src),
        Err(err) => println!("{}", err)
    }
}


参考にしました。
rust - What is this question mark operator about? - Stack Overflow