I am using Nom , the parser combinator, to write a TOML parser. The parser function I am having trouble with parses a date time string using the chrono crate. Here's the code ( playground link ):
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)))
}
}
}
In the code above, I am parsing a string slice using chrono::DatetTime::parse_from_rfc3339
, which returns a chrono::format::ParseResult
. Then, I am matching it so I can convert it to a proper nom::IResult
. The ParseResult::Ok
arm is fine, but I cannot write the correct code for ParseResult::Err
. Here's the error I get when compiling the code snippet above:
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>`
The Error
from Error::from_error_kind
is one of Nom's own structs, which does implement the ParseError
trait, just as the E
generic specifies. Why cannot the compiler recognize this?
Whenever you give a function ( offset_datetime
) a generic parameter ( E
), you are promising that the function can work for every possible type that E
could be, subject to its bounds. Your function signature promises to return an IResult
with error type E
. But you do not do that; instead, you return one with error type nom::error::Error
(using Error::from_error_kind
).
One possible fix is to change the function signature to return the concrete error type that the function body actually does:
fn offset_datetime<'a>(input: &'a str) -> IResult<&'a str, TomlValue, Error<&'a str>> {
Another one would be to change the function body to use the generic type the signature claims:
ParseResult::Err(e) => Err(Err::Error(E::from_error_kind(input, ErrorKind::Fail))),
Note that instead of calling from_error_kind
on the concrete type nom::error::Error
, it's calling it on the type variable E
(which has that method because of the E: ParseError
bound).
I'm not familiar with how to use nom
properly, so I can't tell you which of these is more appropriate.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.