Nonsensical error message about mismatched types

With the code

fn foo(env: &mut String)
    -> impl FnMut(&str) -> nom::IResult<&str, &str> {
    nom::bytes::complete::tag("foo")
}

on rustc 1.55.0 and nom 7 I get the error

error[E0308]: mismatched types
  --> src/mve.rs:2:8
   |
2  |     -> impl FnMut(&str) -> nom::IResult<&str, &str> {
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
   | 
  ::: /Users/dan/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-7.0.0/src/bytes/complete.rs:35:6
   |
35 | ) -> impl Fn(Input) -> IResult<Input, Input, Error>
   |      ----------------------------------------------
   |      |
   |      the expected opaque type
   |      the found opaque type
   |
   = note: expected associated type `<impl Fn<(&str,)> as FnOnce<(&str,)>>::Output`
              found associated type `<impl Fn<(&str,)> as FnOnce<(&str,)>>::Output`

Why are the expected and found types the same? This seems like a bug to me. (Unfortunately I couldn't find an example for the error that didn't involve nom.)

1 Like

When you encounter bizarre errors like this one it's usually due to for<'a> lifetimes. I have a minimal repro and I think that if you tie the lifetime of env: &mut String with the lifetime of the &str the closure takes, your code will work (although you'll likely want to make the result of the closure be tied to its input as well, otherwise you'll likely get other errors).

Can you file a ticket asking to improve the diagnostic?

1 Like

Thanks! I pared down your code a bit and filed https://github.com/rust-lang/rust/issues/89620

4 Likes

I think the best way to fix this is by using |s| nom::bytes::complete::tag("foo")(s) instead of nom::bytes::complete::tag("foo").

4 Likes

That is indeed a common solution for these... I should turn it into a machine applicable suggestion :thinking:

4 Likes