Skip to content

Invalid closure lifetime inference #41366

Closed
@phaylon

Description

@phaylon

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);
    };
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-inferenceArea: Type inferenceA-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions