Skip to content
Update rust error authored by umaumax's avatar umaumax
......@@ -104,9 +104,77 @@ pub enum MyError {
## ライブラリを利用しない場合の汎用的なエラー型
`Result<(), Box<dyn std::error::Error>`を関数の返り値に利用すると良い
なお、lifetime付きの`Result<(), Box<dyn std::error::Error + 'a>`とするパターンもある
e.g.
``` rust
fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
```
[Rust エラー処理2020 - 電気ひつじ牧場]( https://cha-shu00.hatenablog.com/entry/2020/12/08/060000#failure%E3%82%AF%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6 )
> 戻り値の型は`Result<T, Box<dyn std::error::Error + Send + Sync + 'static>>`とした方がベターとのことです.
### デバッグのために適当なエラーを利用したい
[Error in std::io - Rust]( https://doc.rust-lang.org/std/io/struct.Error.html )
``` rust
use std::io::{Error, ErrorKind};
// errors can be created from strings
let custom_error = Error::new(ErrorKind::Other, "oh no!");
```
### 1つの関数に複数の種類のエラーが入り交じる場合の返り値のResultの型はどうする?
1. `Result<(),Box<dyn std::error::Error>>`
例えば、ライフタイムを有する構造体をSendした際のエラー型にはライフタイムが含まれており、Boxは利用できない
[Return value lifetime and? - help - The Rust Programming Language Forum]( https://users.rust-lang.org/t/return-value-lifetime-and/44082 )
> This is because Sender::send includes the item type in the error type, which means that it can't be converted into an anyhow error.
まさにこの状態でlifetimeが混じっていると困るパターン
0. 単純に、`Result<(), Box<dyn std::error::Error + 'a>>`でOKであることが判明
1. `Result<(), failure::Error>`を利用すると解決するが、failureはメンテナンスされていないので、別の方法を考える必要がある
2. `anyhow::Result<()>`に対して、`sender.send(frame).or_else(|e| anyhow::bail!("{}", e))?;`とすると問題ない
* これは結局、`crossbeam_channel::SendError<Hoge<'a>>`のエラー含まれているlifetimeが原因なので、これをそのまま返すのではなく、このエラー型を使って新しいエラー型を構築したものを返すことでlifetimeの制約から逃れている
e.g.
``` rust
struct Hoge<'a> {
name: &'a str,
}
struct HogeSender<'a> {
sender: crossbeam_channel::Sender<Hoge<'a>>,
}
impl<'a> HogeSender<'a> {
fn new() -> Self {
let (sender, _receiver) = crossbeam_channel::bounded(1);
Self { sender }
}
fn send_std_box_with_lifetime(
&self,
hoge: Hoge<'a>,
) -> Result<(), Box<dyn std::error::Error + 'a>> {
self.sender.send(hoge)?;
Ok(())
}
fn send_anyhow_result(&self, hoge: Hoge<'a>) -> anyhow::Result<()> {
self.sender.send(hoge).or_else(|e| anyhow::bail!("{}", e))?;
Ok(())
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let hoge = Hoge { name: "lifetime" };
let hoge_sender = HogeSender::new();
hoge_sender.send_std_box_with_lifetime(hoge)?;
// hoge_sender.send_anyhow_result(hoge)?;
Ok(())
}
```
\ No newline at end of file