1

I'm a Rust beginner, writing a nom parser that can parse lines that are colon-separated KEY: VALUEs. I made a base kv parser with named_args that can parse a key-value pair:

named_args!(kv<'a>(key: &'a str)<&'a str, &'a str>,
   do_parse!(
        tag_s!(key) >>
        tag_s!(":") >>
        space0 >>
        value: rest >>
        (value)
   )
);

I put the lifetimes in there to please the compiler.

I've made these two parsers from it:

named!(name<&str,&str>,
    call!(kv, "NAME")
);
named!(get_dimension<&str, i64>,
    map_res!(call!(kv, "DIMENSION"), str::parse::<i64>)
);

To test these, I was writing a generic wrapper, which calls one of these functions with a KEY: {YOUR_VALUE} string, and expects YOUR_VALUE back:

fn test_kv<G: Display + Debug + PartialEq>(
    kvfunc: fn(&str) -> Result<(&str, G), Err<&str>>,
    key: &str,
    value: G,
) {
    assert_eq!(kvfunc(&format!("{}: {}", key, value)), Ok(("", value)));
}

This works fine:

#[test]
fn test_dimension() {
    test_kv(get_dimension, "DIMENSION", 8)
}

But not with the name parser:

#[test]
fn test_name() {
    test_kv(name, "NAME", "some_name")
}

The compiler gives me:

71 |     test_kv(name, "NAME", "some_name")
   |             ^^^^ expected concrete lifetime, found bound lifetime parameter
   |
   = note: expected type `for<'r> fn(&'r str) -> std::result::Result<(&'r str, _), nom::Err<&'r str>>`
              found type `for<'r> fn(&'r str) -> std::result::Result<(&'r str, &'r str), nom::Err<&'r str>> {name}`

This confuses me. Doesn't Result<&str, &str> fit in Result<&str, _>?

Since it works with the map_res'd version, I assume that map_res returns a different value, maybe with a different lifetime.

I think I may have to change the lifetime definitionss of my kv parser, but I'm completely lost as to how/which ones to choose.

  • Please review [Pass a Struct<'a>::method as a `for<'a> Fn(&Foo<'a>)` for use in a closure](https://stackoverflow.com/q/56095637/155423) and see if the answer or any of the linked questions/answers addresses your problem. – Shepmaster May 14 '19 at 18:27
  • Pfff this is hard. I looked at the linked answers but I think I mistitled the question(now corrected), I'm getting E0308, not E0271. I was able to "fix" the issue by adding lifetime annotations to the `test_kv` parameter, but then was getting that my input wasn't living long enough. I think my root issue is having defined the original function as `named_args!(kv<'a>(key: &'a str)<&'a str, &'a str>`, which makes both the keyword input and the output have the same lifetime, and I don't think it should... The combination of macros, lifetimes, and passing functions in Rust is above my level. – Amedee d'Aboville May 14 '19 at 22:28

0 Answers0