Parser Implementation (2)
- 2018-10-24
- Liu, An-Chi 劉安齊
Working on the parser. When I write the following function Parser::new
, I encounter lifetime issue. No matter how I add lifetime syntax 'a
, 'b
in the function. I cannot pass the compiler.
!FILENAME sql/parser.rs
// The old version
struct Parser<'a> {
tokens: Vec<Symbol<'a>>,
}
impl<'a> Parser<'a> {
fn new(message: &'a str) -> Parser<'a> {
let mut s: Scanner<'a> = Scanner::new(message);
let tokens = s.scan_tokens();
Parser { tokens }
}
}
The error is:
error[E0597]: `s` does not live long enough
--> src/sql/parser.rs:12:39
|
12 | let tokens = s.scan_tokens();
| ^ borrowed value does not live long enough
...
15 | }
| - borrowed value only lives until here
|
That’s very wierd, because I expect the lifetime is correct. Anyway, I give up fighting with lifetime.
Therefore, I change the type of Symbol::name
to String
rather than &str
. Then all errors exist, and I don’t need to add lifetime syntax anymore.
!FILENAME sql/parser.rs
use sql::lexer::Scanner;
use sql::symbol::Symbol;
struct Parser {
tokens: Vec<Symbol>,
}
impl Parser {
fn new(message: &str) -> Parser {
let mut s: Scanner = Scanner::new(message);
let tokens: Vec<Symbol> = s.scan_tokens();
Parser { tokens }
}
}
It works very well.
This story tells us, when you implement a struct
in Rust, it is better to let the type String
in the fields. Though it will be stored at heap, but it will be easier with lifetime handling – once using &str
as type, you must add 'a
lifetime for the struct
, and all other fn
or struct
that use this struct
. Also, all objects related to this struct
in lifetime 'a
, will all live as long as 'a
, and it seems not a good idea. So, String
next time.