我正在使用这个错误板条箱创建一个自定义错误类型
use thiserror::Error;
/// ParseTreeError enumerates all possible errors returned by this library.
#[derive(Error, Debug)]
pub enum ParseTreeError {
/// Represents an empty source. For example, an empty text file being given
/// as input to `count_words()`.
#[error("Source contains no data")]
EmptySource,
/// Represents a failure to read from input.
#[error("Read error")]
ReadError,
}
pub struct Parser <'a, T>
where
T: FromStr + PartialEq
{
token_stream: &'a str,
marker: (usize, usize),
}
impl<'a, T> Parser<'a, T>
where
T: FromStr + PartialEq
{
fn test_parse() -> Result<(), ParseTreeError> {
let mut val = T::from_str("5").unwrap();
Ok(())
}
}
这会引发以下错误:
error[E0599]: the method `unwrap` exists for enum `std::result::Result<T, <T as FromStr>::Err>`, but its trait bounds were not satisfied
--> src/tree/parser.rs:65:40
|
65 | let mut val = T::from_str("5").unwrap();
| ^^^^^^ method cannot be called on `std::result::Result<T, <T as FromStr>::Err>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`<T as FromStr>::Err: Debug`
如果我像这个一样映射错误
let mut val2 = T::from_str("5").map_err(|_| ParseTreeError::ReadError).unwrap();
然后不会抛出任何错误。
如果我尝试使用?操作员我得到错误
error[E0277]: `?` couldn't convert the error to `ParseTreeError`
--> src/tree/parser.rs:65:40
|
65 | let mut val1 = T::from_str("5")?;
| ^ the trait `From<<T as FromStr>::Err>` is not implemented for `ParseTreeError`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= note: required by `from`
我需要做什么才能做到?操作员可以自动将错误转换为正确的错误类型,而不必使用map_err?
您的问题与thiserror
完全无关,但可以通过复制
use std::str::FromStr;
fn test_parse<T>() -> Result<(), ()>
where
T: FromStr,
{
let mut val = T::from_str("5").unwrap();
Ok(())
}
那么,问题出在哪里呢?这个问题隐藏在Result
的unwrap
中。只有当我们能够以某种方式在Result<T, E>
:中显示E
时,unwrap
才可用
// vvvvvvvvvvvvv
impl<T, E: fmt::Debug> Result<T, E> {
// ...
fn unwrap(self) -> T {
...
}
}
E
来自哪里?每个FromStr
实现都必须定义相关的错误类型Err
。但是,Err
没有任何约束。它可能实现Debug
,但也可能不实现。由于我们在test_parse
上的特征边界表明,我们可以运行所有只实现FromStr
的T
,所以我们太通用了。我们需要指出的是,test_parse
仅适用于FromStr
和的T
,其相关的Err
类型可以通过Debug
:显示
use std::fmt;
use std::str::FromStr;
fn test_parse<T>() -> Result<(), ()>
where
T: FromStr,
<T as FromStr>::Err: fmt::Debug, // <<<<
{
let mut val = T::from_str("5").unwrap();
Ok(())
}
现在,test_parse
不能再与所有可能的FromStr
实现一起使用,而只能与那些在其关联的Err
类型上也实现Debug
的实现一起使用。这正是我们所需要的。
对于?
运算符,我们需要为ParseTreeError
实现From<<T as FromStr>::Err>
,但是,这被E0207阻止了。