- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
I'm experimenting with a parser combinator and ran into an issue with closure lifetime inference.
This might be a duplicate of #39943, since it uses a similar (but simpler) mechanism to produce the same error message. However, in the code below the error is potentially a lot further away, and since I need to return values from the closure I'm having trouble finding any way to make it work by explicitly specifying a signature. Since it involves more moving parts, I'm also not sure how to confirm if the underlying issue is the same.
I removed all parts that aren't involved in triggering the error message (the original use case has trait methods with related return types).
It comes down to the following error message:
rustc 1.16.0 (30cf806ef 2017-03-10)
error: `content` does not live long enough
  --> <anon>:64:1
   |
62 |         let _ = apply(&content, parser);
   |                        ------- borrow occurs here
63 |     };
64 | }
   | ^ `content` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created
error: aborting due to previous error
And here is the triggering code:
trait Parse<'input> {
    type Output;
}
// needs one parser which has its Output depending on the input
struct AnyParser;
impl<'input> Parse<'input>
for AnyParser {
    type Output = &'input str;
}
// also needs another parser taking a closure that takes a subparsers
// result
fn fold<P, I, F>(parser: P, init: I, fold: F) -> Fold<P, I, F>
{
    Fold {
        parser: parser,
        init: init,
        fold: fold,
    }
}
struct Fold<P, I, F> {
    parser: P,
    init: I,
    fold: F,
}
impl<'input, P, I, F, T> Parse<'input>
for Fold<P, I, F>
where
    P: Parse<'input>,
    I: Fn() -> T,
    F: Fn(T, P::Output) -> T,
{
    type Output = T;
}
// taking the content and the parser together
fn apply<'input, P>(input: &'input str, parser: P)
where
    P: Parse<'input>,
{
    unimplemented!();
}
fn main() {
    let parser = fold(
        AnyParser,
        // these closures seems to make it think the parser holds on to
        // the AnyParser result (which is part of the input)
        || None,
        |_, v| Some(v),
    );
    // rustc says this must outlive the parser, which is unfortunate
    let content: String = "foo".into();
    {
        let _ = apply(&content, parser);
    };
}