泛型FromStr的Rust-Error转换,用不满足的特征边界打开错误



我正在使用这个错误板条箱创建一个自定义错误类型

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(())
}

那么,问题出在哪里呢?这个问题隐藏在Resultunwrap中。只有当我们能够以某种方式在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上的特征边界表明,我们可以运行所有只实现FromStrT,所以我们太通用了。我们需要指出的是,test_parse仅适用于FromStrT,其相关的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阻止了。

最新更新