Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static lifetime of pom::Parser does not specialize / example code should not encourage pom::Parser #54

Open
mcclure opened this issue Dec 4, 2022 · 1 comment

Comments

@mcclure
Copy link
Contributor

mcclure commented Dec 4, 2022

Today I tried to use pom. I got stuck for a long time on this problem:

Say I take the sample code in the README and modify it so that instead of the input being hardcoded in the program, it comes from a string (code linked).

I get this error:

74 |         println!("{:?}", json().parse(input.as_bytes()));
   |                          -------------^^^^^^^^^^^^^^^^-
   |                          |            |
   |                          |            borrowed value does not live long enough
   |                          argument requires that `input` is borrowed for `'static`
75 |     } else {
   |     - `input` dropped here while still borrowed

I don't understand why I need to borrow because it should be okay to drop input immediately. But okay, I add the &. This doesn't work either:

error[E0597]: `input` does not live long enough
  --> src\main.rs:74:34
   |
74 |         println!("{:?}", json().parse(&input.as_bytes()));
   |                          --------------^^^^^^^^^^^^^^^^-
   |                          |             |
   |                          |             borrowed value does not live long enough
   |                          argument requires that `input` is borrowed for `'static`
75 |     } else {
   |     - `input` dropped here while still borrowed

I am new to Rust so maybe I am confused about lifetimes. But I think what is happening here is that the sample code is using pom::Parser. As the docs explain "pom::Parser<I, O> is alias of pom::parser::Parser<'static, I, O>". This means that when json() is created, the parser object is using lifetime 'static, and therefore it requires any data it parse()s to have lifetime 'static. In other words this code can only work on data that lives the entire lifetime of the application, such as an inline constant! This is not usually what you want.

I showed this to more experienced Rust programmers and they seemed surprised that the Rust compiler did not automatically specialize the 'static to a narrower lifetime. But somehow it does not.

The solution is to not use pom::Parser and instead use normal pom::parser::Parser. This requires rewriting every function signature to pass along the lifetime variable, for example fn space() -> Parser<u8, ()> becomes fn space<'a>() -> Parser<'a, u8, ()>. I made this change (code linked) and the code works, even without borrowing input.as_bytes().

I think you need to do one of the following:

  1. Make whatever change is necessary for Rust to figure out, automatically, that 'static is actually something narrower. Did this used to work at some time in the past? (I do not know if this is possible.)

  2. Make it harder to use the static pom::Parser by accident. Probably pom::Parser should be named pom::StaticParser so it is obvious it must be used with static values. Also, you should link some sample code in the documentation (such as the pom-2 code I link above) demonstrating how to use Pom with runtime values. All the sample code right now seems to use pom::Parser.

If someone copy-pastes the current sample code, like I did, they will probably waste a lot of time trying to figure out why it does not work on simple strings until they figure out they must add lifetimes. I think this is the real error being seen in #32.

@J-F-Liu
Copy link
Owner

J-F-Liu commented Dec 5, 2022

Agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants