2016-12-27 63 views
0

我想重写我的解析器,以允许字符串传递到解析方法,而不是被绑定到结构。生锈的解析器结构在锈

以前,我的代码是这样的:

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

,并在我的新代码,我想是这样的:

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

,但好像我在有生之年搞乱一种我不完全适应的方式。我得到的错误是:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 
    --> test.rs:22:35 
    | 
22 |   self.source = Some(source.chars()); 
    |  

处理这个问题的规范方法是什么?我如何获取String并将其克隆到Parser结构的生存期中?

回答

1

完整的错误信息是:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 
    --> src/main.rs:22:35 
    | 
22 |   self.source = Some(source.chars()); 
    |         ^^^^^ 
    | 
help: consider using an explicit lifetime parameter as shown: fn parse(&mut self, source: &'a str) -> Result<Resource, ParserError> 
    --> src/main.rs:21:5 
    | 
21 |  pub fn parse(&mut self, source: &str) -> Result<Resource, ParserError> { 
    | ^

否则因为它表明:

pub fn parse(&mut self, source: &'a str) -> Result<Resource, ParserError> 

允许代码编译和运行(在main固定无关错配可变性后)。


要了解区别,您必须先了解lifetime elision

你原来的代码是:

fn new(source: &str) -> Parser // with elision 
fn new<'b>(source: &'b str) -> Parser<'b> // without elision 

在口头上,一般寿命参数结构的'a被捆绑到输入字符串的寿命。

你的新代码更复杂:

fn new() -> Parser<'b> 

// with elision 
fn parse(&mut self, source: &str) -> Result<Resource, ParserError> 
// without elision 
fn parse<'c, 'd>(&'c mut self, source: &'d str) -> Result<Resource, ParserError> 

在口头上,一般寿命参数struct的'a仍由的new调用者定义的,但现在它不依赖于从构造函数什么。当调用parse时,您试图传递一个不相关生命期的字符串并存储对它的引用(通过Chars迭代器)。由于两个生命周期不相关,所以你不能确定它会持续多久。