Rust newbie question, how to handle error in this function?

Viewed 156

I'm learning Rust with the nom crate and below is my program.

fn get_indent_level(input: &str) -> usize {
    let (_, result) = many0_count(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    result
}

I got this error when run it:

error[E0283]: type annotations needed
   --> src\lib.rs:149:23
    |
149 |     let (_, result) = many0_count(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    |                       ^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the function `many0_count`
    | 
   ::: C:\Users\user1\.cargo\registry\src\github.com-xxxxxxxxxxxxxxx\nom-6.2.1\src\multi\mod.rs:486:6
    |
486 |   E: ParseError<I>,
    |      ------------- required by this bound in `many0_count`
    |
    = note: cannot satisfy `_: ParseError<&str>`
help: consider specifying the type arguments in the function call
    |
149 |     let (_, result) = many0_count::<I, O, E, F>(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    |                                  ^^^^^^^^^^^^^^

When I added the types like this:

fn get_indent_level(input: &str) -> usize {
    let (_, result) = many0_count::<&str, usize, nom::error::ErrorKind, &str>(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    result
}

I got this new error:

error[E0277]: the trait bound `nom::error::ErrorKind: ParseError<&str>` is not satisfied
   --> src\lib.rs:149:23
    |
149 |     let (_, result) = many0_count::<&str, usize, nom::error::ErrorKind, &str>(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or...
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ParseError<&str>` is not implemented for `nom::error::ErrorKind`
    | 
   ::: C:\Users\user1\.cargo\registry\src\github.com-xxxxxxxxxx\nom-6.2.1\src\multi\mod.rs:486:6
    |
486 |   E: ParseError<I>,
    |      ------------- required by this bound in `many0_count`

What's the proper way to add types and fix the issue?

1 Answers

You only need to specify the error type, because nom can return different error types and the compiler cannot infer it, because the error is not used anywhere. You can use the _ syntax to let the compiler infer the rest of the known types.

The easiest way is to specify the types on the IResult type, because it requires less types than many0_count():

fn get_indent_level(input: &str) -> usize {
    let result: IResult<_, _, nom::error::Error<_>> =
        many0_count(alt((
            tag("L_ "), 
            tag("|  "),
            tag("   ")
        )))(input);
    result.map(|(_, x)| x).unwrap_or_default()
}

In that way you only need to provide 3 types, 2 of which are already known (the input - &str; and the result - usize) so you can let the compiler infer them using the _ syntax and manually write only the error type.

Related