Extending borrow lifetimes in rust

南楼画角 提交于 2019-11-28 11:10:28

问题


I'm trying to parse a series to tokentrees, but when I try to implement my parsing trait I get an error related to reference lifetimes. I thought creating a boxed version would move around any issues with reference counts or lifetimes. The code is as follows.

impl Parse for TokenTree {
    fn parse(&mut self) -> Tree {
        match self.clone() {
            TtDelimited(_, y) => {
                let mut y2 = box (*y).clone();
                match y2.delim {
                    token::DelimToken::Paren => y2.parse(),
                    _ => panic!("not done yet"),
                }
            }
            TtToken(_, t) => E(t),
            _ => panic!("not done yet"),
        }
    }
}

the errors I get make the issue clear, but I can't find any information on solving this particular issue.

35:51 error: `*y2` does not live long enough
                     token::DelimToken::Paren => y2.parse(),
                                                       ^~
42:6 note: reference must be valid for the anonymous lifetime #1 defined on the block at 30:31...
 fn parse(&mut self) -> Tree{ 
     match self.clone(){
         TtDelimited(_, y) => {
             let mut y2 = box () (*y).clone();
             match y2.delim{
                 token::DelimToken::Paren => y2.parse(),
       ...
 38:14 note: ...but borrowed value is only valid for the block at 32:33
         TtDelimited(_, y) => {
             let mut y2 = box () (*y).clone();
             match y2.delim{
                 token::DelimToken::Paren => y2.parse(),
                 _ => panic!("not done yet"),
             }

回答1:


In this code:

{
    let mut y2 = box (*y).clone();
    match y2.delim {
        token::DelimToken::Paren => y2.parse(),
        _ => panic!("not done yet"),
    }
}

You create y2, which will only live until the block exits. You didn't include your trait, but my guess is that parse returns a reference to the object itself, something like:

fn parse(&self) -> &str

The reference can only last as long as the object, otherwise it'd point to invalid data.

Edit: How it could maybe, possibly work

You have to track the lifetime of the string you are tokenizing and tie your tokens lifetime to that input:

enum Token<'a> {
  Identifier(&'a str),
  Whitespace(&'a str),
}

trait Parser {
    // Important! The lifetime of the output is tied to the parameter `input`,
    // *not* to the structure that implements this! 
    fn parse<'a>(&self, input: &'a str) -> Token<'a>;
}

struct BasicParser;

impl Parser for BasicParser {
    fn parse<'a>(&self, input: &'a str) -> Token<'a> {
        Token::Identifier(input)
    }
}


来源:https://stackoverflow.com/questions/27570978/extending-borrow-lifetimes-in-rust

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!