I'm trying to rewrite my parser to allow for strings to be passed into the parse method, instead of being bound to the struct.
Previously, my code looked like this:
use std::collections::HashMap;
use std::str;
#[derive(Debug)]
pub enum ParserError {
Generic
}
pub struct Resource(
pub HashMap<String, String>
);
pub struct Parser<'a> {
source: str::Chars<'a>
}
impl<'a> Parser<'a> {
pub fn new(source: &str) -> Parser {
Parser { source: source.chars() }
}
pub fn parse(&mut self) -> Result<Resource, ParserError> {
let entries = HashMap::new();
Ok(Resource(entries))
}
}
fn main() {
let parser = Parser::new("key1 = Value 1");
let res = parser.parse();
}
and in my new code I'm trying something like this:
use std::collections::HashMap;
use std::str;
#[derive(Debug)]
pub enum ParserError {
Generic
}
pub struct Resource(
pub HashMap<String, String>
);
pub struct Parser<'a> {
source: Option<str::Chars<'a>>
}
impl<'a> Parser<'a> {
pub fn new() -> Parser<'a> {
Parser { source: None }
}
pub fn parse(&mut self, source: &str) -> Result<Resource, ParserError> {
self.source = Some(source.chars());
let entries = HashMap::new();
Ok(Resource(entries))
}
}
fn main() {
let parser = Parser::new();
parser.parse("key1 = Value 1");
parser.parse("key2 = Value 2");
}
but it seems like I'm messing with lifetimes in a way that I'm not fully comfortable with. The error I get is:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> test.rs:22:35
|
22 | self.source = Some(source.chars());
|
What's the canonical way of handling this? How can I take a String
and clone it into the lifetime of the Parser
struct?
The full error message is:
Doing as it suggests:
Allows the code to compile and run (after fixing the unrelated mismatched mutability in
main
).To understand the difference, you must first understand lifetime elision.
Your original code was:
In words, the generic lifetime parameter
'a
of the struct was tied to the lifetime of the incoming string.Your new code was more complicated:
In words, the generic lifetime parameter
'a
of the struct is still defined by the caller ofnew
, but now it's not tied to anything from the constructor. When callingparse
, you were attempting to pass in a string of an unrelated lifetime and store a reference to it (through theChars
iterator). Since the two lifetimes were unrelated, you cannot be sure it will last long enough.