借用检查器不允许我在调用设置器之后调用获取器。

3

我一直在用Rust编写一个简单的词法分析器。然而,我遇到了“错误[E0502]: 无法将'a_rule'借用为不可变的,因为它也被作为可变的借用”问题。我查看了其他答案,但似乎找不到原因。

pub struct Rule<'a> {
    selector: &'a str,
}

impl<'a> Rule<'a> {
    pub fn new(selector: &'a str) -> Self {
        Self {
            selector
        }
    }

    pub fn get_selector(&'a self) -> &'a str {
        self.selector
    }

    pub fn set_selector(&'a mut self, selector: &'a str) {
        self.selector = selector
    }
}

#[cfg(test)]
mod tests {
    use super::Rule;

    #[test]
    fn set_selector_test() {
        let mut a_rule = Rule::new(".foo");
        a_rule.set_selector(".bar");

        assert_eq!(a_rule.get_selector(), ".bar")
    }
}

错误:

error[E0502]: cannot borrow `a_rule` as immutable because it is also borrowed as mutable
  --> src/lib.rs:30:20
   |
28 |         a_rule.set_selector(".bar");
   |         ------ mutable borrow occurs here
29 | 
30 |         assert_eq!(a_rule.get_selector(), ".bar")
   |                    ^^^^^^
   |                    |
   |                    immutable borrow occurs here
   |                    mutable borrow later used here

Playground

我也想借此机会问一下,是否建议使用像Java中的get和set方法,还是将结构体中的成员设置为public。

请随意指出任何其他愚蠢的错误。


错误地在外部作用域中使用'a,而一个新的生命周期就足够了,这是一个常见的错误。我认为这是链接方法中self和引用的生命周期的重复,或者可能是从那里链接的其他问题之一。 - trent
1个回答

3
你已经通过将get_selectorset_selector的参数设为&'a self/&'a mut self,将你的规则生命周期绑定到了字符串的生命周期上,但这不是它们之间正确的关系。你可以生成&'a str而不需要让你的self一直存在(或被借用为可变),因为self.selector已经是一个&'a str

移除self参数中的'a引用:

pub fn get_selector(&self) -> &'a str {
    self.selector
}

pub fn set_selector(&mut self, selector: &'a str) {
    self.selector = selector;
}

(但你真的需要这个getter和setter吗?考虑不可变性!)


整个生命周期似乎有些混乱,逻辑上 setter 应该接受一个比 self 存活时间更长的 str,而 getter 应该返回从 self 借用的 str。在我的看法中,这只能在使用 'static 的情况下才能正常工作,此时最好直接将其键入为 'static,不是吗? - Masklinn
@Masklinn,&str 不必是 'static,它只需要存活至少与 'a 一样长的时间即可——这就是有生命周期注释的全部意义,不是吗?如果引用必须是 'static,那么你根本不需要注释 Rule - trent
有人能解释一下编译器的借用错误和生命周期之间的关系吗?编译器似乎在抱怨当你已经有一个可变借用时还有一个不可变借用。但解决方法是改变生命周期... - drootang
1
@drootang 终身注释是告诉编译器借用应该持续多长时间的方法。让可变借用保持更长时间,即超过 'a 的寿命,会导致它与不可变借用重叠。去除此限制可以使编译器缩短借用时间并不再重叠。 - trent
@trentcl 从技术上讲是可以的,但实际上由于它在结构体中存储引用,所以使用非“static”字符串编写任何有用代码的机会相当低。 - Masklinn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接