为什么 rust 'pub fn func(&'a mut self)' 在运行后被认为是“可变借用的”?

Jam*_*979 4 rust

tl;dr given pub fn func(&'a mut self),为什么运行后被self认为是“可变借用的” ? func

鉴于以下最小可行示例(操场

pub struct Struct1<'a> {
    var: &'a u8,
}

impl<'a> Struct1<'a> {
    pub fn new() -> Struct1<'a> {
        return Struct1 {
            var: &33,
        }
    }
    pub fn func(&'a mut self) -> () {
        ()
    }
}

fn main() {
    let mut s1 = Struct1::new();
    s1.func();  // point 1
                // point 2
    s1.func();  // point 3
}
Run Code Online (Sandbox Code Playgroud)

导致编译器错误

error[E0499]: cannot borrow `s1` as mutable more than once at a time
  --> src/test12-borrow-mut-struct-twice-okay.rs:20:5
   |
18 |     s1.func();  // point 1
   |     -- first mutable borrow occurs here
19 |                 // point 2
20 |     s1.func();  // point 3
   |     ^^
   |     |
   |     second mutable borrow occurs here
   |     first borrow later used here
Run Code Online (Sandbox Code Playgroud)

然而,// point 2s1 我看来,以不能再借。在func完成运行。有什么能仍然可以借self之内func!?看来func//point 1已放弃的控制s1

什么是借款还是s1// point 3


类似问题:

Mas*_*inn 10

// 点 3 处仍在借用 s1 的是什么?

你告诉编译器它仍然是借来的,所以它信任你:虽然编译器验证你的生命周期不是太短,但它并不真正关心它们是否太长以至于无法使用。

当您编写时&'a mut self, the'a是在impl块上声明的那个,因此是在结构上定义的那个。&'a mut self 字面意思是

self: &'a mut Struct1<'a>
Run Code Online (Sandbox Code Playgroud)

所以一旦你调用func()了 rust 编译器,“好吧,this 被借用于'awhich 与s1which is相关的生命周期'static,所以这将永远被可变地借用,美好的一天”,因此你被“锁定”在结构之外。

实际上,您可以通过尝试显式声明'aon来查看此别名func

    pub fn func<'a>(&'a mut self) -> () {
        ()
    }
Run Code Online (Sandbox Code Playgroud)
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
  --> src/main.rs:11:17
   |
5  | impl<'a> Struct1<'a> {
   |      -- first declared here
...
11 |     pub fn func<'a>(&'a mut self) -> () {
   |                 ^^ lifetime `'a` already in scope

error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)

所以 rust 毫不含糊地告诉你,块内'a总是指在impl块上声明的生命周期。

解决方案是删除'a,这完全是错误的生命周期:

error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
  --> src/main.rs:11:17
   |
5  | impl<'a> Struct1<'a> {
   |      -- first declared here
...
11 |     pub fn func<'a>(&'a mut self) -> () {
   |                 ^^ lifetime `'a` already in scope

error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)

在这种情况下 rustc 将自动引入生命周期,并且由于该函数实际上并没有借用任何东西,因此生命周期只会扩展到函数调用。

  • 与“s1”相关的生命周期不是“静态”;它是一个尚未由编译器确定的生命周期 `'a`,但它至少涵盖了 `s1` 超出范围之前的时间。这仍然意味着任何对 `func()` 的调用只要它存在就借用 `s1`,所以它不会改变你给出的推理的任何内容。 (3认同)
  • 啊! 事实上,我的实际程序(而不是这里的示例程序)是在我删除结构函数上不必要的生命周期时编译的。极好的!既然你指出了这一点,那就非常明显了。我是一个 rust n00b,我_认为_我更好地理解了生命周期(尽管我一直告诉自己“_我想我现在理解了 rust_”,但后来我没有)。非常感谢! (2认同)

归档时间:

查看次数:

67 次

最近记录:

5 年 前