Reputation: 110
I am new to Rust and I am trying to create combinator parser in it. Here is the code:
enum Parser<T: Copy + Eq> {
Ok,
Eof,
Satisfy { predicate: Box<dyn Fn(&T) -> bool> },
Element { elem : T }
}
impl<T: Copy + Eq> Parser<T> {
fn parse<'a, P>(&self, input: &'a [T]) -> Option<(&'a [T], P)>
where
P: Default,
T: Into<P>
{
match self {
Parser::Ok => Some((input, P::default())),
Parser::Eof => match input {
[] => None,
_ => Some((input, P::default())),
},
Parser::Satisfy { predicate } => match input {
[] => None,
[x, rest @ ..] => {
if predicate(x) {
Some((rest, T::into(*x)))
} else {
None
}
}
},
Parser::Element { elem } => {
let to_match = *elem;
Parser::Satisfy { predicate: Box::new(move|x| *x == to_match) }.parse(input)
}
}
}
}
Parser::Ok, Parser::Eof and Parser::Satisfy are working fine but I struggled with realization of Parser::Element (which must much only exact element). I want to realize method parse for it with creation of Parser::Satisfy with predicate of eq between argument x and given elem. But I run into this error:
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:32:46
|
32 | Parser::Satisfy { predicate: Box::new(move|x| *x == to_match) }.parse(input)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
8 | impl<T: Copy + Eq + 'static> Parser<T> {
| +++++++++
I feel there is some problem with lifetimes but I do not know how to fix it.
Upvotes: 0
Views: 61
Reputation: 70830
dyn Trait
contains things. These things may have lifetimes. Therefore, dyn Trait
also has a lifetime.
This lifetime, like functions' lifetimes, can be elided. The full rules are somewhat complicated, but when in an ADT, the lifetime is assumed to be 'static
. You can specify another lifetime with dyn Trait + 'lifetime
.
Thus, the Box<dyn Fn(&T) -> bool>
in your enum is actually Box<dyn Fn(&T) -> bool + 'static>
.
But the problem is that the function you assign into it captures to_match
, of type T
. And type T
may contain a non-'static
lifetime. For example, it may contain &'non_static str
. This is the error.
This has two possible solutions.
Either accept that and require T
to be 'static
:
impl<T: Copy + Eq + 'static> Parser<T> {
Or allow non-'static
lifetime for the function:
enum Parser<'a, T: Copy + Eq> {
Ok,
Eof,
Satisfy { predicate: Box<dyn Fn(&T) -> bool + 'a> },
Element { elem : T }
}
impl<T: Copy + Eq> Parser<'_, T> {
Upvotes: 2