読者です 読者をやめる 読者になる 読者になる

日曜プログラミング

休日趣味でやってるプログラミング関連記事をダラダラと

Rust で try! マクロが上手く動かなかった

Rust 絶賛学習中なんだけども、try! を 使用したサンプルが動かなかったのでメモとして残す。 原因はちゃんと追ってないが、状況と回避方法だけ。 (と言っても try! マクロ使わないようにするってだけだけど)

2016-05-08 追記

原因分かった。未読だったエラーハンドリング を読んでtry! の API docでのサンプル見てやっと理解した。

Result を返す関数の中で記述を簡略化する為のものなのね。 Rust の main は戻り値が無い(()を返す) 所に try!マクロ内の処理が失敗すると return Err が返るようになってるからコンパイルエラーになると。

けどそれならそれでサンプルは何がしかの Result を返す関数内で使うサンプルにすべきじゃないのかなあ。 まだまだ勉強が足りんかな。

と言うわけで単にtry!を使わないようにすると言うのはプロトタイピングレベルじゃなければやらないようにすべきなので 冒頭のは完全に消しはしないけど打ち消し線つけさせておいてもらいます。

環境

> rustc --version
rustc 1.8.0 (db2939409 2016-04-11)

状況

ファイル IO をやってみたくて API doc のサンプルコンパイルするとコンパイルエラー発生。

fn main() {
    use std::io::prelude::*;
    use std::fs::File;
    
    let mut buffer = try!(File::create("foo.txt"));
    
    try!(buffer.write(b"some bytes"));
}
<std macros>:5:8: 6:42 error: mismatched types:
 expected `()`,
    found `core::result::Result<_, _>`
(expected (),
    found enum `core::result::Result`) [E0308]
<std macros>:5 return $ crate:: result:: Result:: Err (
<std macros>:6 $ crate:: convert:: From:: from ( err ) ) } } )
main.rs:37:22: 37:51 note: in this expansion of try! (defined in <std macros>)
<std macros>:5:8: 6:42 help: run `rustc --explain E0308` to see a detailed explanation
<std macros>:5:8: 6:42 error: mismatched types:
 expected `()`,
    found `core::result::Result<_, _>`
(expected (),
    found enum `core::result::Result`) [E0308]
<std macros>:5 return $ crate:: result:: Result:: Err (
<std macros>:6 $ crate:: convert:: From:: from ( err ) ) } } )
main.rs:39:5: 39:39 note: in this expansion of try! (defined in <std macros>)
<std macros>:5:8: 6:42 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to 2 previous errors

エラーメッセージ見るとマクロ展開時に期待する型じゃないとか言われた。 けど API doc じゃ File::createは Result 返すし try! マクロ も Result を返すもので使うみ たいな事書いてあるのに、エラーメッセージはどうもそうなってない。

とりあえず try! を使用しないようにすればファイル書き込みはいけた。

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

    let mut buffer = File::create("foo.txt").expect("cannot create file.");

    buffer.write(b"some bytes");
}

マクロのコードも追っかけてみたいけどまだ Rust でのマクロの作り方は全く学習してないので保留。