- 回復可能なエラー - ファイルが見つからない など - [[Result]]で制御 - 回復不能なエラー - [[配列 (Rust)|配列]]の境界を越えた箇所にアクセス など - [[panicマクロ]] ## [[panicマクロ|panic!]]で回復不能なエラー - `RUST_BACKTRACE=1`で[[スタックトレース]]を出せる ## Resultで回復可能なエラー - [[マッチガード]] - `Err(ref error) if ...` の `ref` は `error` が[[マッチガード]]にムーブしないためのもの - `Err(&error) if ...` では参照に対して[[パターンマッチ (Rust)|パターンマッチ]]してしまうため型違いでエラーになる ```rust use std::fs::File; use std::io::ErrorKind; fn main() { let f = File::open("hoge"); let f = match f { Ok(file) => file, Err(ref error) if error.kind() == ErrorKind::NotFound => { panic!("Not found"); } _ => { panic!("Unexpected error"); } }; eprintln!("f = {:?}", f); } ``` - `.expect(...)`で`.unwrap()`と同じ動きをしつつ失敗時のエラーメッセージを決定 ```rust fn main() { let f = File::open("hoge"); let f = f.expect("hogehogehoge not found!!"); } // thread 'main' panicked at 'hogehogehoge not found!!: Os { code: 2, kind: NotFound, message: "指定されたファイルが見つかりません。" }', src\main.rs:6:15 ``` 上記は`unwrap`で表示される情報プラスアルファになっている。 ```rust fn main() { let f = File::open("hoge"); let f = f.unwrap(); } // thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "指定されたファイルが見つかりません。" }', src\main.rs:6:15 ``` - [[アーム]]の中で`return`を使うと関数の戻り値になる - [[Question mark operator]] - エラー型変換の`from`関数を通る たとえば - オリジナルのエラーが型 `MyError`は`From<io::Error>`を実装する - `io:Error`から`MyError`への変換が可能 - `File::open`は`io::Error`を返す という状況で[[Question mark operator]]を使うと、[[戻り値型]]である`MyError`は`io::Error`を受けて変換できるポテンシャルを秘めているため、このコードはコンパイルが通る。 ```rust use std::fs::File; use std::io; use std::io::Error; struct MyError {} impl From<io::Error> for MyError { fn from(_: Error) -> Self { MyError {} } } fn func() -> Result<File, MyError> { let r = File::open("hoge")?; Ok(r) } fn main() { let f = func(); } ``` ## panic!すべきかするまいか - [[Rustでpanicマクロを使うとき、使わないとき]] - [[構造体 (Rust)|構造体]]の[[インスタンス (Rust)|インスタンス]]生成関数 (`new`) でバリデーションする例 - [[Result]]でなく[[panicマクロ]]使うのね... - ユーザー入力のときはどっちがいいのかな? - 自分は[[Result]]使って、そのままそれをUIにも利用してた - [[panicマクロ]]で落としつつ、UI側でも同じvalidationを書けばいい? - それって二度手間でメンテ辛いから賛同はしかねる