Anyone know how to implement thiserror#[from] on a PoinsonError ?
I have my error type WindowError with a variant which should be build from a PoisonError<GlobalState> (to use ? on the .read() method of Arc<RwLock<GlobalState>>) :
error[E0277]: `?` couldn't convert the error to `WindowError`
--> gui/src/window/part/header.rs:9:34
|
9 | match self.state().read()?.state() {
| ^ the trait `From<PoisonError<RwLockReadGuard<'_, GlobalState>>>` is not implemented for `WindowError`, which is required by `Result<(), WindowError>: FromResidual<Result<Infallible, PoisonError<RwLockReadGuard<'_, GlobalState>>>>`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the trait `From<PoisonError<GlobalState>>` is implemented for `WindowError`
= help: for that trait implementation, expected `GlobalState`, found `RwLockReadGuard<'_, GlobalState>`
= note: required for `Result<(), WindowError>` to implement `FromResidual<Result<Infallible, PoisonError<RwLockReadGuard<'_, GlobalState>>>>`
Any help ? I tried to include RwLockReadGuard in my #[from] type, but seem not the way (lifetime, etc ...)
Your source error type is not PoisonError<GlobalState>, it's PoisonError<RwLockReadGuard<'_, GlobalState>>, as clearly pointed out by the very error message you pasted.
PoisonErrorshould not be wrapped and passed on. PoisonError carries the lock guard so you can ignore poison if you want, but that means that the lock is still locked as long as you hold the PoisonError, and it is probably a bad idea to do that longer than necessary — it could cause deadlock. And as you have already discovered, the lifetime makes it difficult to do anyway.
Also, PoisonError indicates that something has gone wrong previously — there was previously a panic — so it may be unwise to try to recover from, and .unwrap() may be better handling.
But if you do decide you want to include this case in your error type, the answer is to not try to put the PoisonError itself in your struct. Define a StateAccessError variant without a field, and use .map_err() or a custom From implementation to convert to that variant while dropping the PoisonError.