Confusing opaque type with nom

I am writing a nom parser ,(which i can't show as its huge). My issue is the weird compile error i get

error[E0308]: mismatched types
   --> arkley_algebra\src\parser\tokens.rs:127:20
    |
71  |     fn parse_nested_expression<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec<Token>> {
    |                                         --------------------------------------------------- the expected opaque type
...
123 |         let map_term = map(parse_term,|term| Vec::from([Token::from(term)]) );
    |                                       ------ the found closure
...
127 |             mapper(map_term),
    |             ------ ^^^^^^^^ expected opaque type, found a different opaque type
    |             |
    |             arguments to this function are incorrect
    |
   ::: C:\Users\Aarav Aditya Shah\.cargo\registry\src\index.crates.io-6f17d22bba15001f\nom-7.1.3\src\combinator\mod.rs:73:60
    |
73  | pub fn map<I, O1, O2, E, F, G>(mut parser: F, mut f: G) -> impl FnMut(I) -> IResult<I, O2, E>
    |                                                            ---------------------------------- the found opaque type
    |
    = note: expected opaque type `impl FnMut(&str) -> Result<(&str, Vec<Token>), nom::Err<nom::error::Error<&str>>>` (opaque type at <arkley_algebra\src\parser\tokens.rs:71:41>)
               found opaque type `impl FnMut(&str) -> Result<(&str, Vec<Token>), nom::Err<nom::error::Error<&str>>>` (opaque type at <C:\Users\Aarav Aditya Shah\.cargo\registry\src\index.crates.io-6f17d22bba15001f\nom-7.1.3\src\combinator\mod.rs:73:60>)
    = note: distinct uses of `impl Trait` result in different opaque types
note: closure parameter defined here
   --> arkley_algebra\src\parser\tokens.rs:100:23
    |
100 |         let mapper = |first_parser| map(parser(first_parser),|(lexpr,rexpr) : (Vec<Token>,Option<Vec<Token>>)|{
    |                       ^^^^^^^^^^^^

In this the 'expected' and 'found' type are litterally the same.

Things that made be related to the error

// needs <'a> or without it , it gives worst error 
fn parse_nested_expression<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec<Token>> {
    todo!()
}

//  let map_term = map(parse_term,|term| Vec::from([Token::from(term)]) );

// in context of 

fn idk() {
       alt((
            mapper(Self::parse_nested_expression()),
            mapper(map_term),
        ))(input)
}

I think you're running into this

@quinedot Is right. To understand the reason behind why the compiler wants the two types to be the same, a playground that produces you error would help.

Old answer, I think it's a different issue

This diagnostics problem is well-known, I ran into it as well, and I find it very annoying. There are many many duplicates on the issue tracker about this and a big meta issue at 30+ duplicates on E0308 with expected and found being literally identical · Issue #112985 · rust-lang/rust · GitHub.
There or in the linked issues are explanations what the error means.

1 Like

The key to understanding the error is the second note.

note: distinct uses of impl Trait result in different opaque types

For example.


I've never found nom to be intuitive. I see alt requires the same input/output/error, maybe that''s related. It's not clear to me what your mapper function is though. (Let me know and I'll give it another shot.)


Outdated note related to the post above

Most[1] of those are about higher-ranked versus not-higher-ranked types, which isn't the error in the OP.


  1. all? didn't check ↩︎

Oh, I just noticed your error box was scroll-barred and has mapper at the bottom.

let mapper = |first_parser|  ...

Closures can't be generic over types.[1] That's probably why you're getting an error about the type mismatch: everything you pass to mapper has to be the same type.[2]

If it's possible, using something like this instead might fix the problem.

fn mapper<F>(f: F) -> impl FnMut(&str) -> IResult<...>
where
    F: FnMut(&str) -> IResult<...>

(Not entirely sure about the details, nom is messy. The point is to make a function which can be generic over types.)


  1. only lifetimes ↩︎

  2. modulo lifetimes ↩︎

1 Like

You maybe right , but I couldn't find a way to convert my 'mapper parser' into a function that accepts a single parser. (As I want to reuse logic and only one parser changes).Hence I choose to use a closure (the source of all my problems :sweat_smile:)

Oh that makes much more sense, it means that the contents of the closure or impl Trait are different hence the error?. If I understand it correctly

  • (Once I am able to get on my computer , I will post a snippet of the mapper closure)

Here is the mapper function as promised

fn parse_with_opt_implicit_mul(input: &str) -> IResult<&str,Vec<Token>> {
        let parser = |first_parser| separated_pair(
            first_parser,
            multispace0,
            opt(Token::parse_expression)
        );

        let mapper = |first_parser| map(parser(first_parser),|(lexpr,rexpr) : (Vec<Token>,Option<Vec<Token>>)|{
            let mut vec = vec![];
            
            vec.push(Token::OpenParenthesis);

            vec.extend(lexpr.into_iter());

            vec.push(Token::CloseParenthesis);

            if let Some(value) = rexpr {
                vec.push(ArithmeticOperation::Mal.into());

                vec.push(Token::OpenParenthesis);

                vec.extend(value.into_iter());
    
                vec.push(Token::CloseParenthesis);
    
            }
          
            vec
        });

        let map_term = map(parse_term,|term| Vec::from([Token::from(term)]) );

        alt((
            mapper(Self::parse_nested_expression()),
            mapper(map_term),
        ))(input)
    }

I've managed to get it to compile by converting parser and mapper to normal functions, please try this. (I've added some dummy definitions to make it compile.)

1 Like

Yes thank you that compiles , I'll mark that as the answer :blush:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.