Rust でエラー型に Clone が実装されていてほしい
これは物申す系の話とかではなく、単なる愚痴。
現状については現状セクション参照。
概要
-
エラー云々以前に、ユーザが後から (
Clone
等、自前でない trait の)実装を追加できない以上、ライブラリ作者はできるだけ基本的な trait 群を derive しておくべきである。
-
エラー型のオブジェクトを clone したい場合が存在する。
- error_chain crate でエラー型を用意すると、現状(0.11.0 ( リリース)時点)では
derive(Clone)
できない。
以上のような理由で、つらい。
エラーを clone したい状況
処理の完了や致命的な失敗の後にも、 Result を返す関数の呼び出しに制約をかけたくない場合
たとえば XML パーサである xml-rs crate 等が該当する。
xml::reader::EventReader::next()
は、(致命的な)パースエラー等があると Err
を返すが、エラーが返された後も next()
自体は制限なく何度でも呼び出すことができる。
このような場合、最後のエラーを複数回返す必要が出てくるため、当然エラー型は Clone
を実装していてほしい。
以前、私が xml-rs を参考に書いた fbx_direct crate では、エラーとして I/O エラー (std::io::Error
) が有り得たため、自前で Clone
を実装することになってしまった。
Qiita の記事『Rustで std::io::Error をcloneしたいとき - Qiita』はこのときの副産物である。
完了や失敗の後の関数呼び出しに制約をかけるというのもひとつの選択で、たとえば futures-rs などはその選択を採っている。
futures-rs の Future
trait 自体は各ライブラリ開発者が各々の型に対して実装しうるものであり、エラー型も様々だから、実装を単純にするためにこのように定めたのであろう。
エラー型を致命的でない警告に対して使いたい場合
コンセプト (サンプルコード)
致命的でない警告をエラーとして扱うかどうかユーザに委ねたい場合などがあり、この場合警告は Error
trait を実装していると良い。
コード例を書いたので参照されたい (playground へのリンク)。
警告のエラー型が Clone
を実装していてほしいのは、まさに最後の例のような場合である。
エラーをどこかに記憶(複製)したのち確認したい場合、 clone()
できてほしいし、 assert_eq!()
等でテストをしたい場合には Clone
以外にも PartialEq
なども必要になるから、 Clone
に限らず基本的な trait はとにかく実装しておいてほしいということである。
具体例: fbxcel crate (自作)
先述の fbx_direct crate とは別に(というか改良して)、 fbxcel という crate を開発していて、こちらでは、致命的ではないがおかしいデータについて Warning
型で警告を発するようになっている。
単なるロギングではなく、こうして専用の型のついたオブジェクトを経由させることで、このライブラリを利用するアプリケーションからも警告履歴を利用可能となる。
具体例: fsck-xv6 (自作)
いつぞやの OS の授業の課題で xv6 のファイルシステムの validator (fsck-xv6) を実装したことがあり、このときもファイルシステムエラーを表現するための型に Error
trait を実装した。
こちらは一般的な意味での「エラー」ではあるが、ファイルシステムの妥当性検証という性質上、ファイルシステムのエラーがそのままプログラムの継続不可能を意味するわけではない。
よって、複数のエラーが発生すればそれらを全て列挙したり、或いは Vec
等のコンテナに溜めたりといった用途を想定することになる。
この設計は fbxcel のエラー処理の発想をそのまま使ったものであり、ゆえに結局警告をエラーとして使いたいのかそうでないのかよくわからない設計になっている。
今の私が同じような目的のコードを書いたら、最初の例のように特定の警告にフックをかけて処理を中断できるように作るはずである。
現状
ここまで熟々と書いてきたのは、つまるところエラーを clone したいというだけの話である。
現状でそれを妨げる要因は、以下のようなものである。
error-chain trait がエラー型に対する derive をサポートしていない
error-chain crate は、エラー型や関連する諸々を用意する際のボイラープレートを減らすためのライブラリである。
イマドキ手書きの温かみのあるエラー型を書いたりしないよね、 error-chain は人権だよねという空気がある[要出典]が、残念ながら error-chain で定義したエラー型は Clone
を実装していないのである!!!
()
プルリクエストもあり議論は進んでいるようだが、今使いたい私にとっては重大な問題である。