この記事では、Rustのビルトインエラーにバックトレース情報を付加する方法を解説します。ここでは、anyhow
クレートを使用してその問題を解決する方法について説明します。
ビルトインエラーの問題点
Rustのビルトインエラーは便利ですが、「デフォルトではバックトレース情報が付加されていません」という問題点があります。これにより、エラーの原因を特定するのが困難になる場合があります。例えば、次のようなコードがあります。
use std::num::ParseIntError;
fn main() {
let err: Result<(), ParseIntError> = stack1();
eprintln!("{err:?}");
}
fn stack1() -> Result<(), ParseIntError> {
stack2()?;
Ok(())
}
fn stack2() -> Result<(), ParseIntError> {
parse_int()?;
Ok(())
}
fn parse_int() -> Result<i32, ParseIntError> {
"invalid".parse::<i32>()
}
このコードを実行すると、エラーメッセージが次のように表示されます。
Err(ParseIntError { kind: InvalidDigit })
この結果から、エラーが ParseIntError
であることはわかりますが、どの関数で問題が発生したのかは明らかになりません。
解決策: anyhowクレートを使用する
エラーが発生したスタックフレーム情報を含むバックトレースがあれば、開発者はエラーの原因を特定しやすくなります。
anyhow
クレートは、エラー処理を簡単にするためのライブラリで、バックトレース情報を付加する機能も含まれています。以下のステップに従って、上記の問題を解決していきます。
ステップ1: 依存関係を追加する
Cargo.toml
に以下の依存関係を追加します。
[dependencies]
anyhow = { version = "1.0.70", features = ["backtrace", "std"] }
anyhowの backtrace
と std
のfeaturesを有効にすることで、バックトレース情報をサポートし、エラーハンドリングで標準エラーからanyhow::error:Error
への変換も手軽に扱えるようになります。
ステップ2: コードにあてはめる
以下のコードスニペットは、anyhow
を使用してバックトレースを含むエラーを生成する方法を示しています。
fn main() {
let err: Result<(), anyhow::Error> = stack1();
eprintln!("{:#?}", err);
}
fn stack1() -> Result<(), anyhow::Error> {
stack2()?;
Ok(())
}
fn stack2() -> Result<(), anyhow::Error> {
parse_int()?;
Ok(())
}
fn parse_int() -> Result<i32, anyhow::Error> {
"invalid".parse::<i32>().map_err(|e| e.into())
}
ライブラリエラーを返す可能性がある関数の呼び出しは、?
でプロパゲーションする前に into()
を使って anyhow::Error
に変換することで、バックトレース情報が適切に付加されます。
ステップ3: バックトレースを表示する
バックトレースを表示するには、RUST_BACKTRACE
環境変数を1に設定してプログラムを実行します。これにより、バックトレース情報が有効になります。
RUST_BACKTRACE=1 cargo run
これにより、以下のようなバックトレースが表示されます。
Err(invalid digit found in string
Stack backtrace:
...
8: parse_int
at ./src/main.rs:20:5
9: stack2
at ./src/main.rs:12:5
10: stack1
at ./src/main.rs:7:5
11: main
at ./src/main.rs:2:42
...
この結果から、エラーが parse_int
関数で発生したことがわかります。また、stack1
と stack2
の関数もバックトレースに表示されています。
まとめ
この記事では、anyhow
を使って Rust のビルトインエラーにバックトレース情報を付加する方法を紹介しました。これにより、開発者がエラーの原因を特定しやすくなり、デバッグが容易になります。
関連