anyhowを使う

anyhow::Error

https://docs.rs/anyhow/1.0.44/anyhow/struct.Error.html

動的エラー型を包み込んだエラー型。

Box<dyn std::error::Error>との違い

  • 静的な型
  • もどり道(backtrace)を保証する
  • narrow pointer

Display representations

Display 表し方

esprintln!("{}", err)

undering error(anyhow::Errorが包み込んだerror) もしくは、contextを表示する。

例: Failed to read instrs from ./path/to/instrs.json

esprintln!("{:#}", err)

anyhowのcausesのデフォルトフォーマットを出力する

例: Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2)

esprintln!("{:?}", err)

キャプチャーしたバックトレースを出力する。

例: Error: Failed to read instrs from ./path/to/instrs.json

Caused by: No such file or directory (os error 2)

anyhow::Result<T>

実態

//anyhow
type Result = Result<T, anyhow::Error>

fn mainでは返すことができない。 anyhow::Errorを伝搬してくれる。

anyhow::Context

Result<T, anyhow::Error>に変換するcontextメソッドを提供する。

std::core::Result<T, E>からの変換

let file = File::open("memo.txt").context(format!("unable to open memo.txt)")?;

Option<T>からの変換

let first = vec.first()?.context("unable to get first from vec")

anyhow! bail!

anyhow!マクロ

anyhow::Errorをかんたんに生成

例: stringからの生成

fn lookup(key: &str) -> Result<V> {
    if key.len() != 16 {
        return Err(anyhow!("key length must be 16 characters, got {:?}", key));
    }

    ...

bail!マクロ

実態

return(anyhow!($args....))

これを使うことでかんたんにanyhow::Result<T>にして返すことができる

if !has_permission(user, resource) {
    bail!("permission denied for accessing {}", resource);
}

thiserrorとの組み合わせ

#[derive(Error, Debug)]
enum ScienceError {
    #[error("resouce limit exceeded")]
    RecursionLimitExceeded,
    ...
}

if depth > MAX_DEPTH {
    bail!(ScienceError::RecursionLimitExceeded);
}