cilmutulta
cilmutulta

Reputation: 21

Cannot infer type for type parameter Error when parsing with nom

I have this test with nom version 7.1:

use nom::bytes::complete::tag;

#[test]
fn test() {
    let (s, t) = tag("1")("123").unwrap();
}

Running cargo test gives

error[E0283]: type annotations needed
  --> src/main.rs:5:18
   |
5  |     let (s, t) = tag("1")("123").unwrap();
   |                  ^^^ cannot infer type for type parameter `Error` declared on the function `tag`
   |
   = note: cannot satisfy `_: ParseError<&str>`
note: required by a bound in `nom::bytes::complete::tag`
  --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-7.1.0/src/bytes/complete.rs:32:29
   |
32 | pub fn tag<T, Input, Error: ParseError<Input>>(
   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `nom::bytes::complete::tag`
help: consider specifying the type arguments in the function call
   |
5  |     let (s, t) = tag::<T, Input, Error>("1")("123").unwrap();
   |                     +++++++++++++++++++

It suggests I specify tag::<T, Input, Error>()

How do I deal with this? I have not fully understood why this problem arises.

I tried specifying some types from nom:

use nom::bytes::complete::tag;

#[test]
fn test() {
    let (s, t) = (tag::<_, &str, nom::error::ParseError<&str>>("1")("123")).unwrap();
}
error[E0782]: trait objects must include the `dyn` keyword
 --> src/main.rs:5:34
  |
5 |     let (s, t) = (tag::<_, &str, nom::error::ParseError<&str>>("1")("123")).unwrap();
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
5 |     let (s, t) = (tag::<_, &str, dyn nom::error::ParseError<&str>>("1")("123")).unwrap();
  |                                  +++

error[E0277]: the size for values of type `dyn ParseError<&str>` cannot be known at compilation time
  --> src/main.rs:5:19
   |
5  |     let (s, t) = (tag::<_, &str, nom::error::ParseError<&str>>("1")("123")).unwrap();
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn ParseError<&str>`
note: required by a bound in `nom::bytes::complete::tag`
  --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-7.1.0/src/bytes/complete.rs:32:22
   |
32 | pub fn tag<T, Input, Error: ParseError<Input>>(
   |                      ^^^^^ required by this bound in `nom::bytes::complete::tag`

error[E0038]: the trait `ParseError` cannot be made into an object
 --> src/main.rs:5:34
  |
5 |     let (s, t) = (tag::<_, &str, nom::error::ParseError<&str>>("1")("123")).unwrap();
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ParseError` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

Upvotes: 1

Views: 1724

Answers (1)

Shepmaster
Shepmaster

Reputation: 430921

Nom has a generic error type:

Parsers are generic over their error type, requiring that it implements the error::ParseError<Input> trait.

This means that your code needs to specify the desired error type; the code in the question does not.

As the compiler suggests: consider specifying the type arguments in the function call. One of the implementors of ParseError would be a good place to start. Nom provides two:

Picking one:

use nom::{bytes::complete::tag, error::Error};

#[test]
fn test() {
    let (_s, _t) = tag::<_, _, Error<_>>("1")("123").unwrap();
}

See also:

Upvotes: 6

Related Questions