Error トレイトの定義を確認してみた

に公開

前々回は Result<T, E> について書き前回は Result<T, E> のよく使うメソッドについて書きました

Rust の Result<T, E>TE は任意の型を使用できます。ただ E は多くの場合 Error トレイトを実装した型を指定します。

……というわけで今回は Rust の標準ライブラリにある Error トレイトについて書いてみます。

ちなみに、 Rust API ガイドラインの項目に Result<T, E>E のようなエラー型は Error トレイトを実装すべきと明記してあります。

https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err

Error トレイトの定義

改めて。 std::error::Error トレイトはエラー値に期待される基本的な性質を表現します。例えば Result<T, E>E の型の値です……的なことがドキュメントの 1 行目から書いてあります。

Error トレイトの定義はだいたいこんな感じです。

trait Error: Debug + Display {
    fn source(&self) -> Option<&(dyn Error + 'static)>;
    // deprecated since 1.42.0
    fn description(&self) -> &str;
    // deprecated since 1.33.0
    fn cause(&self) -> Option<&dyn Error>;
    // nightly-only
    fn provide<'a>(&'a self, request: &mut Request<'a>);
}

4 つあるメソッドのうち、 3 つは deprecated と nightly-only です。 stable を想定すれば「 Debug と Display を実装していて source メソッドがある」程度のものですね。

無視するつもりのものをざっと見ると……。

descriptionDisplayto_string で代替されています。

causesource で代替されています。

provide はあまりよく分かっていないですが、エラー報告用のコンテキストデータを提供するためのものっぽいですね。 Backtrace のコード例が示されています。

DebugDisplay

Error のスーパートレイトとして指定されている DebugDisplay ですが、これらも標準のトレイトです。

Debugformat!{:?} と指定したときの文字列形式、 Displayformat!{} と指定したときの文字列形式ですね。前者は開発者向け (デバッグ用途) 、後者はユーザー向けの出力ですね。

description の代替であることから、エラーを説明するような文字列に to_string で変換されることが想定されていそうです。

Display の例

さきほども紹介した Rust API ガイドラインの項目に ErrorDisplay の形式についても記載があります。

https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err

The error message given by the Display representation of an error type should be lowercase without trailing punctuation, and typically concise.

「小文字で、句読点をつけない」とのこと。

次のような例も示されているので、途中に単語として大文字が混じるのは良さそうですね。

  • "unexpected end of file"
  • "provided string was not true or false"
  • "invalid IP address syntax"
  • "second time provided was later than self"
  • "invalid UTF-8 sequence of {} bytes from index {}"
  • "environment variable was not valid unicode: {:?}"

Error::source

Error::sourcecause を代替していることから分かるように、エラーの原因になった、より低レベルなエラーを返すものです。

なければなくて (None) で良いと。 前にも書いた Option ですね。

次回予告

thiserror crate を使いながら実装します (たぶん) 。 downcast を試しても良さそう (普段は使っていない) 。

GitHubで編集を提案
ドクターメイト

Discussion