gpt4 book ai didi

rust - 如何正确解决结构中的生命周期推断?

转载 作者:行者123 更新时间:2023-12-03 11:45:01 26 4
gpt4 key购买 nike

rust playground code is here .
我有一个 Token 结构,它的生命周期为 'tok ,并且扫描仪的生命周期为 'lexer .我在另一个结构解析器中使用它们,然后我遇到了一个问题:

pub struct Token<'tok> {
pub value: Cow<'tok, str>,
pub line: usize,
}

pub struct Scanner {
pub source: Vec<char>,
pub current: usize,
pub line: usize,
}

pub struct Parser<'lexer> {
pub curr: &'lexer Token<'lexer>,
pub prev: &'lexer Token<'lexer>,
scanner: &'lexer mut Scanner,
}

impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
self.prev = self.curr;
self.curr = &self.scanner.next(); // cannot inference lifetime
}
}
我认为问题是 Token 有生命周期 'tok , 借用检查器不知道 'tok 之间的关系和 'lexer所以它不能推断出正确的生命周期。
但是,我可以通过将其修改为 the updated code 来避免该问题。 :
pub struct Parser<'lexer> {
pub curr: Token<'lexer>,
pub prev: Token<'lexer>,
scanner: &'lexer mut Scanner,
}

impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
let prev = std::mem::replace(&mut self.curr, self.scanner.next());
self.prev = prev;
}
}
并使用 next() 制作的 Token是静态的:
impl Scanner {
pub fn next(&mut self) -> Token<'static> {
Token {
value: Cow::from(""),
line: 0,
}
}
}
它确实可以编译,但我认为这并不理想,因为所有标记都从扫描仪克隆到解析器(它们不再是引用)并一直存在到解析器生命的尽头。所以内存使用量翻了一番。有没有更合适的方法来处理这个问题?

最佳答案

实际上,您的代码结构对于处理借用检查器并不理想,原因如下:

  • Token结构体应该被拥有,结构体本身不需要任何分配(因为 token 是拥有的,所以需要一些间接方法来允许上一个 <-> 下一个切换)
  • 没有ParserLexer应该拥有基础数据,因此很容易绑定(bind)适当的生命周期
  • 在我们的案例中 Vec<Char>不是一个友好的类型(我们不需要拥有数据,这将使编译器更难理解生命周期),相反我们将使用 &'str 但您可以使用&[字符])

  • 这是一个编译得很好的例子
    pub struct Token<'source> {
    pub value: Cow<'source, str>,
    pub line: usize,
    }

    pub struct Scanner<'source> {
    pub source: &'source str,
    pub current: usize,
    pub line: usize,
    }

    pub struct Parser<'source> {
    pub curr: Option<Token<'source>>,
    pub prev: Option<Token<'source>>,
    scanner: Scanner<'source>,
    }
    impl <'source>Scanner<'source> {
    pub fn next(&'source /* DONT Forget to bound 'source to `self` */ self) -> Token<'source> {
    Token {
    value: Cow::from(self.source), /* `self.source` is bound to `'source` so the compiler understand that the token lifetime is the same than the source's one */
    line: 0,
    }
    }
    }

    impl <'lexer> Parser<'lexer> {
    pub fn advance(&'lexer mut self) {
    self.prev = self.curr.take();
    self.curr = Some(self.scanner.next());
    }
    }

    关于rust - 如何正确解决结构中的生命周期推断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63397254/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com