Rust 嵌套数据结构的可变性

6
有人能解释一下为什么以下代码会编译通过,但如果我注释掉其中一行,那么它就无法编译通过,即使代码本质上执行相同的操作?
struct OtherStruct {
  x: i32,
}

struct Inner {
  blah: i32,
  vector: Vec<OtherStruct>
}

struct Outer {
  inner: Inner,
}

impl Inner {
  pub fn set_blah(&mut self, new_val : i32) {
    self.blah = new_val;
  }
}

fn main() {
  let mut outer = Outer {
    inner: Inner {
      blah: 10,
      vector: vec![
        OtherStruct { x: 1 },
        OtherStruct { x: 2 },
        OtherStruct { x: 3 },
        OtherStruct { x: 4 },
        OtherStruct { x: 5 },
      ]
    }
  };

  for item in outer.inner.vector.iter() {
    println!("{}", item.x);
    outer.inner.blah = 4;
    //outer.inner.set_blah(6);
  }

}

编译器错误如下:

   |
34 |   for item in outer.inner.vector.iter() {
   |               -------------------------
   |               |
   |               immutable borrow occurs here
   |               immutable borrow later used here
...
37 |     outer.inner.set_blah(6);
   |     ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here

我能理解这个问题,但我想知道为什么我在不使用函数调用时仍然可以轻易实现它,毕竟同样会出现可变性问题?


1
来自Niko Matsakis的非常相关的博客文章:After NLL: Interprocedural conflicts - Sven Marnach
1个回答

4

set_blah 需要借用整个 Inner 结构体对象。对于 blah 的赋值只需要借用该字段本身,这是行得通的,因为它尚未被借用。


2
为了补充:借用检查器能够在结构层面上执行部分借用,但是函数对于借用检查器来说是不透明的。借用检查器可以看穿对inner.vectorinner.blah的访问,并理解它们是不重叠的,但是它无法看穿set_blah,因此就像它所关心的那样,总是借用整个结构。 - Masklinn
另外,@Masklinn所说的是有意为之,而不是借用检查器的技术限制。这样做可以使得像set_blah()这样的方法的推理和向后兼容性保证基于其_签名_而不是其内容,因为其内容可能在另一个crate中。 - user4815162342

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