Closed7

Rustのエラーハンドリング

ピン留めされたアイテム
hayaohayao

結局どう書けばいい?

Rustのエラーハンドリングは過渡期でベストプラクティスはないらしい。とはいえ、どう書くかを選択する必要がある。

参考文献

TODO

  • anyhowとthiserrorについての理解を深める
  • RustConf 2020: Error Handing Isn't All About Errors視聴する
hayaohayao

Enumeration

自前でラップ

pub enum CopyError {
  In(std::io::Error),
  Out(std::io::Error),
}

やるべきこと

  • std::io::Errorトレイトを実装する。
  • DisplayDebugを実装する。
    • Display 何を誤ったかの一行の描写 小文字 句読点なし
  • Debug より説明的なエラー
  • (可能なら)SendSyncを実装する。
  • (可能なら)'staticにする。

Erasure

Box化

type erased error
Box<dyn Error + Send + Sync + 'static>

Errorトレイト

 pub trait Error: Debug + Display {
  fn source(&self) -> Option<&(dyn Error + 'static)> {
   None
  }
}

Resultで必要とされているように見えるが実はそうではない。

  pub enum Result<T, E> {
    Ok(T),
    Err(E),
}

じゃあErrorトレイトの使いみちは?
→意味的にこれがエラーであるとマークすること。

良いエラーとは

  • 異なった表現(DebugDisplay)を実装すること、異なった慣習に合わせて。
  • 下に横たわるエラーを見ることを可能にすること。
hayaohayao

sourceメソッドの目的はerror chainに深く潜ること。

hayaohayao

エラーハンドリングの明日

https://blog.rust-lang.org/inside-rust/2021/07/01/What-the-error-handling-project-group-is-working-towards.html

現在の問題

現在のコンテキストをうっかりで失ってしまうことが容易。
失いうる場所

  • エラーをプリントするときsourceをプリントするのを忘れる。
  • mainからエラーを戻す時
  • 回復可能なエラーを回復不可能なエラーに変換するとき

問題点

unwrapexpectDebugimplを使ってエラーを文字列化する。が
その過程でErrorトレイトによって注意深く分割されたコンテキストの断片を失っていしまう。

Rustのパニック機構をError型をパニックに変換する機構を持っていない。←これが主要な問題だと思っている。

今日の(間に合せの?)解決策

Debugトレイトを悪用すること。= Debugのアウトプットが人間が読める形でエラーチェーン全体をプリントするようにする。 eyreanyhowがやっていること。

ただし、この方法では派生した我々のエラーのDebug形式にアクセスできない。デバッグに必要な内部の詳細が隠される可能性があるが、これはユーザが読むことを目的としてエラーメッセージの一部ではない。

hayaohayao

独自のエラー構造体を実装してenumでまとめてFromトレイトを実装するメリットは?

エラーごとに独自のの情報を保持できる

hayaohayao

疑問

anyhow::Resultは人のエラー型に対してFromを実装している?

box化されたエラー型から具体的な値を取得する方法は存在する? downcast

単一種類のエラーを返す場合

好きにすれば良いがエラー型は実装しといた方が良い。なぜなら?でボックス化されたエラーに変換できる

複数種類のエラーを返す場合

enumかbox
具体的なエラー型を使ってなにかしたい場合等はenum パターンマッチで取れる
レポートするだけならbox

このスクラップは2021/11/13にクローズされました