# Lost in generic inference and lifetimes with Nom, and it's only a 6-statement function!

**URL:** <https://users.rust-lang.org/t/lost-in-generic-inference-and-lifetimes-with-nom-and-its-only-a-6-statement-function/68120>\
**Category:** help\
**Created:** [December 1, 2021, 3:45am UTC](https://users.rust-lang.org/t/lost-in-generic-inference-and-lifetimes-with-nom-and-its-only-a-6-statement-function/68120 "2021-12-01T03:45:44Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![Heliozoa](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/heliozoa/32/16524_2.png) [@Heliozoa](https://users.rust-lang.org/u/Heliozoa)\
**Post date:** [December 1, 2021, 2:50pm UTC](https://users.rust-lang.org/t/lost-in-generic-inference-and-lifetimes-with-nom-and-its-only-a-6-statement-function/68120/2 "2021-12-01T14:50:35Z")

</div>

> [@QuantumET](#):
>
> But why did I need to specify it, and what other choices were there?

There are also implementations for `nom::error::Error`, `nom::error::VerboseError` and `()`. You can try replacing `(&str, nom::error::ErrorKind)` with any of these and they will all work, so the compiler needs help in figuring out which one you want. (It would also need such a hint even if there was only one implementation, because it wouldn't be nice if adding a second implementation broke code relying on there only being one.)

I don't know if nom has some more convenient way of selecting the concrete error type, but one option is to annotate the variable instead of the function

```rust
let parse: Result<_, nom::Err<(_, _)>> = tuple(( // ...

```

> [@QuantumET](#):
>
> And it's really not at all clear to me where `'static` could even be applied in these 6 lines of code! Which makes me suspect adding `'static` isn't actually the right thing to do, but I'm not sure what would be.

The `'static` error is a bit unhelpful as is often the case, in this case it's trying to tell you that instead of a temporary `str` borrow, you should use a permanent `'static` one, meaning changing the function signature to

```rust
fn parse_password_line(i: &'static str) -> Result<(u64, u64, char, &str), io::Error> {

```

which, as you've correctly guessed, would probably result in unsolveable errors elsewhere.

The reason it tries suggesting this is a bit convoluted, but to simplify it a bit, [std::io::Error::new](https://doc.rust-lang.org/std/io/struct.Error.html#method.new) wants something that can be converted into a trait object that does not hold any temporary borrows. nom's errors contain the unparsed input data, which means that this conversion cannot be done when the input data is temporarily borrowed from elsewhere (`i: &str`). The naive fix is to simply make the borrow permanent (`i: &'static str`).

Using `to_string` like you have is fine, I think, but if you want to keep the `nom::Err`, it offers a function nom::Err::map\_input, which we can use to turn the problematic temporarily borrowed input into an owned `String`.

```rust
        Err(e) => Err(io::Error::new(
            io::ErrorKind::InvalidData,
            e.map_input(|e| e.to_string()),
        )),

```

APIs that use lots of generics like nom's are a bit hard to wrap your head around and I don't have great advice for that, unfortunately. One good trick is to type annotate something wrong to get a compiler error telling you what it actually is. Examples are often valuable too, [here](https://github.com/Geal/nom/blob/main/examples/string.rs#L168) you can see that they've made the parsing function `parse_string` generic over the error type, and it is then called with the error type annotated.

---

_[View the full topic](https://users.rust-lang.org/t/lost-in-generic-inference-and-lifetimes-with-nom-and-its-only-a-6-statement-function/68120)._
