Cannot infer type for type parameter `I` declared on the function `tuple` when parsing with nom

1.3k Views Asked by At

I am trying to use nom's tuple function. The documentation presents the following example:

use nom::sequence::tuple;
use nom::character::complete::{alpha1, digit1};
let parser = tuple((alpha1, digit1, alpha1));

When I try it out, I get a compile error:

    error[E0283]: type annotations needed
   --> src/main.rs:20:18
    |
20  |     let parser = tuple((alpha1, digit1, alpha1));
    |         ------   ^^^^^ cannot infer type for type parameter `I` declared on the function `tuple`
    |         |
    |         consider giving `parser` a type
    | 

If I wanted to add a type to the variable, what would it be? I know it has to be some variation of FnMut, but I am unsure how it would work exactly.

Cargo.toml

[dependencies]
nom = ">=5.0"
1

There are 1 best solutions below

1
On BEST ANSWER

Type inference requires enough information to actually infer the type. You can either provide the required information by copying the full example from the documentation, including the two assert_eq!() statements:

use nom::sequence::tuple;
use nom::character::complete::{alpha1, digit1};
let mut parser = tuple((alpha1, digit1, alpha1));

assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def"))));
assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha))));

The additional calls inform the compiler about the argument and return type of the function returned by tuple(), which in turn gives the compiler enough information to infer all type parameters of the tuple() call.

Alternatively, you can explicitly pass type parameters to the tuple() function. Here is the minimal amount of information you need to provide for Rust to be able to infer all types:

let _parser = tuple::<&str, _, (_, _), _>((alpha1, digit1, alpha1));

Note that the details of how type inference works in Rust are not part of the language specification, and may change in future versions of Rust. While Rust has quite strong backwards compatibility guarantees, you sometimes may need to add some type annotations to your code when upgrading to a newer version.