[Solved] More Rust/combine lifetime issues

  1. Minimal failure care:
use combine_language::LanguageEnv;
use combine::easy;
use core::fmt;
use std::fmt::Formatter;
use combine::Parser;
use std::error::Error;

pub struct FooParser<'a> {
    env: LanguageEnv<'a, easy::Stream<&'a str>>,
}

#[derive(Debug)]
pub struct MyError {}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", 1)
    }
}

impl Error for MyError {}

type MyParser<'a, T> = Box<Parser<Input=easy::Stream<&'a str>, Output=T, PartialState=()> + 'a>;

impl <'a> FooParser<'a> {
    pub fn char_e (&self) -> MyParser<'a, char> {
        let t = self.env.char_literal();
        /*
        .and_then(|c: char| -> Result<Expr, MyError> {
            Ok(Expr::Chr(c))
        });
        */
        Box::new(t)
    }
}
  1. errors I get:
   |
27 |         let t = self.env.char_literal::<'a>();
   |                          ^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 26:5...

   |
26 | /     pub fn char_e (&self) -> MyParser<'a, char> {
27 | |         let t = self.env.char_literal::<'a>();
28 | |         /*
29 | |         .and_then(|c: char| -> Result<Expr, MyError> {
...  |
33 | |         Box::new(t)
34 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content

   |
27 |         let t = self.env.char_literal::<'a>();
   |                 ^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 25:7...

   |
25 | impl <'a> FooParser<'a> {
   |       ^^
   = note: ...so that the expression is assignable:
           expected std::boxed::Box<(dyn combine::parser::Parser<Output=char, Input=combine::stream::easy::Stream<&'a str>, PartialState=()> + 'a)>
              found std::boxed::Box<dyn combine::parser::Parser<Output=char, Input=combine::stream::easy::Stream<&str>, PartialState=()>>

How do I fix this? And what are the clues from the rustc error message? In general, I seem competent at readcig rustc error msgs, but these ones from rust/combine are constantly confusing me.

1 Like

char_literal() borrows from env - that's the 'b lifetime in combine_language::LanguageEnv - Rust. So your char_e cannot return MyParser<'a, char> because that doesn't capture the fact you also have a shorter borrow from self.

You should be able to do the following though:

pub fn char_e (&self) -> MyParser<'_, char> {
        let t = self.env.char_literal();
        /*
        .and_then(|c: char| -> Result<Expr, MyError> {
            Ok(Expr::Chr(c))
        });
        */
        Box::new(t)
    }

This extends the shared borrow of self though, which may or may not work for your follow on code.

1 Like

I ended up rewriting the code in a way to not face this problem. However, I appreciate the suggestion/response.