Rust编译器无法识别为结构实现的泛型特征绑定



我正在使用语法分析器组合子Nom来编写TOML语法分析器。我遇到的解析器函数使用chrono crate解析日期时间字符串。

fn offset_datetime<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, TomlValue, E> {
match DateTime::parse_from_rfc3339(input) {
ParseResult::Ok(dt) => IResult::Ok(("", TomlValue::OffsetDateTime(dt))),
ParseResult::Err(e) => {
Err(Err::Error(Error::from_error_kind(input, ErrorKind::Fail)))
}
}
}

游乐场

在上面的代码中,我使用chrono::DatetTime::parse_from_rfc3339解析一个字符串切片,它返回一个chrono::format::ParseResult。然后,我对其进行匹配,以便将其转换为适当的nom::IResultParseResult::Ok臂很好,但我无法为ParseResult::Err编写正确的代码。以下是我在编译上面的代码片段时遇到的错误:

error[E0308]: mismatched types
--> src/parser.rs:193:28
|
188 | fn offset_datetime<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, TomlValue, E> {
|                        - this type parameter
...
193 |             Err(Err::Error(Error::from_error_kind(input, ErrorKind::Fail)))
|                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `E`, found struct `nom::error::Error`
|
= note: expected type parameter `E`
found struct `nom::error::Error<&str>`

Error::from_error_kind中的Error是Nom自己的结构之一,它确实实现了ParseError特性,正如E泛型所指定的那样。为什么编译器不能识别这一点?

无论何时给函数(offset_datetime(一个泛型参数(E(,都承诺该函数可以适用于E可能是的所有类型,受其边界限制。您的函数签名承诺返回错误类型为EIResult。但你不这么做;相反,您返回一个错误类型为nom::error::Error的(使用Error::from_error_kind(。

一个可能的解决方案是更改函数签名,以返回函数体实际执行的具体错误类型:

fn offset_datetime<'a>(input: &'a str) -> IResult<&'a str, TomlValue, Error<&'a str>> {

另一种方法是将函数体更改为使用签名声明的通用类型:

ParseResult::Err(e) => Err(Err::Error(E::from_error_kind(input, ErrorKind::Fail))),

请注意,它不是在具体类型nom::error::Error上调用from_error_kind,而是在类型变量E上调用它(由于E: ParseError绑定,它具有该方法(。

我不熟悉如何正确使用nom,所以我无法告诉你哪一个更合适。

最新更新