Skip to content
Update rust error authored by umaumax's avatar umaumax
...@@ -118,7 +118,7 @@ ResultのEがErrorトレイトを満たす単なる構造体については`?` ...@@ -118,7 +118,7 @@ ResultのEがErrorトレイトを満たす単なる構造体については`?`
そのまま返すと`trait `Sized` is not implemented`となるので、間に変換を挟む必要がある そのまま返すと`trait `Sized` is not implemented`となるので、間に変換を挟む必要がある
(このテクニックはlifetime境界が含まれるエラー型から新規の`'static`なエラー型を生成する場合にも使える) (このテクニックはlifetime境界が含まれるエラー型から新規の`'static`なエラー型を生成する場合にも使える)
参考: [Explicit constructor from Box<dyn Error + Send + Sync> · Issue #83 · dtolnay/anyhow]( https://github.com/dtolnay/anyhow/issues/83 ) 参考: [Explicit constructor from Box\<dyn Error + Send + Sync> · Issue #83 · dtolnay/anyhow]( https://github.com/dtolnay/anyhow/issues/83 )
[Error in anyhow - Rust]( https://docs.rs/anyhow/1.0.44/anyhow/struct.Error.html#impl-From%3CError%3E )`Send``Sync`なしの`impl From<Error> for Box<dyn StdError + 'static>`も存在するが、 [Error in anyhow - Rust]( https://docs.rs/anyhow/1.0.44/anyhow/struct.Error.html#impl-From%3CError%3E )`Send``Sync`なしの`impl From<Error> for Box<dyn StdError + 'static>`も存在するが、
ソースコードを見るとラップされているだけであり、内部では`impl From<Error> for Box<dyn StdError + Send + Sync + 'static>`を呼びだす ソースコードを見るとラップされているだけであり、内部では`impl From<Error> for Box<dyn StdError + Send + Sync + 'static>`を呼びだす
...@@ -132,7 +132,7 @@ ResultのEがErrorトレイトを満たす単なる構造体については`?` ...@@ -132,7 +132,7 @@ ResultのEがErrorトレイトを満たす単なる構造体については`?`
自然に`Send``Sync`の条件を満たしているので、特に意識することなく、`From`トレイトによって、自動変換されていることがわかる 自然に`Send``Sync`の条件を満たしているので、特に意識することなく、`From`トレイトによって、自動変換されていることがわかる
ただし、 ただし、
[rust - Why doesn't Box<dyn Error> implement Error? - Stack Overflow]( https://stackoverflow.com/questions/65151237/why-doesnt-boxdyn-error-implement-error ) [rust - Why doesn't Box\<dyn Error> implement Error? - Stack Overflow]( https://stackoverflow.com/questions/65151237/why-doesnt-boxdyn-error-implement-error )
にある通り、下記のように変換しようとすると`Sized`が実装されておらず変換できない にある通り、下記のように変換しようとすると`Sized`が実装されておらず変換できない
``` rust ``` rust
let box_error: Box<dyn std::error::Error + Send + Sync + 'static> = todo!(); let box_error: Box<dyn std::error::Error + Send + Sync + 'static> = todo!();
...@@ -302,3 +302,56 @@ std::fs::File::open(path).with_context(|| format!("Failed to open config file: { ...@@ -302,3 +302,56 @@ std::fs::File::open(path).with_context(|| format!("Failed to open config file: {
``` ```
`use anyhow::Context`によって、`std::error::Error``.context()`などが生える `use anyhow::Context`によって、`std::error::Error``.context()`などが生える
## `ensure!`の調査
要約: `failchain::ensure`を利用するか内部で定義するかの2通りがある
* [failchain::ensure - Rust]( https://docs.rs/failchain/latest/failchain/macro.ensure.html ): `Err($e.into())`
* `ensure!`が任意のエラー型で利用可能!!
* 有名ではないが、`ensure!`のみならば特に問題ないのでは?
* [snafu::ensure - Rust]( https://docs.rs/snafu/0.6.10/snafu/macro.ensure.html ): `.fail().map_err(::core::convert::Into::into);`
* `ensure!``.fail()`を持つ型で利用可能...
* [ensure in anyhow - Rust]( https://docs.rs/anyhow/1.0.51/anyhow/macro.ensure.html ): `private::Err(anyhow!())`
* `anyhow::Error`以外では`ensure!`が利用できない...
* 凍結注意 [failure::ensure - Rust]( https://docs.rs/failure/latest/failure/macro.ensure.html ): `failure::Error`
* 凍結注意 [error_chain::ensure - Rust]( https://docs.rs/error-chain/0.12.4/error_chain/macro.ensure.html ): `Err($e.into())`
* 内部定義例
* [minsc/macros.rs at master · shesek/minsc]( https://github.com/shesek/minsc/blob/master/src/macros.rs )
* [zola/lib.rs at master · getzola/zola]( https://github.com/getzola/zola/blob/master/components/errors/src/lib.rs )
* [notify-rust/error.rs at main · hoodie/notify-rust]( https://github.com/hoodie/notify-rust/blob/main/src/error.rs )
FYI: [Err($e.into()) - grep.app]( https://grep.app/search?q=Err%28%24e.into%28%29%29 )
``` rust
#[macro_export]
#[doc(hidden)]
macro_rules! ensure {
($cond:expr, $e:expr) => {
if !($cond) {
crate::bail!($e);
}
};
($cond:expr, $fmt:expr, $($arg:tt)*) => {
if !($cond) {
crate::bail!($fmt, $($arg)*);
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! bail {
($e:expr) => {
return Err($e.into());
};
($fmt:expr, $($arg:tt)+) => {
return Err(format!($fmt, $($arg)+).into());
};
}
```
内部クレートの他のモジュールから利用する場合には下記の宣言が必要
``` rust
use crate::ensure;
use crate::bail;
```
\ No newline at end of file