Skip to content
GitLab
Menu
Why GitLab
Pricing
Contact Sales
Explore
Why GitLab
Pricing
Contact Sales
Explore
Sign in
Get free trial
Changes
Page history
Update rust error
authored
Oct 14, 2021
by
umaumax
Show whitespace changes
Inline
Side-by-side
rust/rust-error.md
View page @
a0f2860f
...
...
@@ -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