可变借款似乎比其范围更长

时间:2015-09-04 17:47:16

标签: rust

尝试编译这个程序我被卡在借用检查器上:

use std::collections::BTreeMap;

type Object<'a> = BTreeMap<&'a str, i32>;

struct Root<'a>(Object<'a>);

struct Sub<'a>(&'a mut Object<'a>, &'a str);

impl<'a> Root<'a> {
    fn borrow_mut(&'a mut self, data: &'a str) -> Sub<'a> {
        Sub(&mut self.0, data)
    }

    fn borrow(&self) {
        println!("{:?}", self.0);
    }
}

fn main() {
    let mut me = Root(Object::new());
    {
        me.borrow_mut("data!");
    }
    me.borrow();
}

Playground

我明白了:

error[E0502]: cannot borrow `me` as immutable because it is also borrowed as mutable
  --> src/main.rs:24:5
   |
22 |         me.borrow_mut("data!");
   |         -- mutable borrow occurs here
23 |     }
24 |     me.borrow();
   |     ^^ immutable borrow occurs here
25 | }
   | - mutable borrow ends here

看起来可变借用应该在me.borrow()之前结束,但是借用检查器坚持在main结束时结束。

快速解释我想要完成的事情:

  1. 创建一个父结构来保存数据
  2. 创建子类别的数据并将其存储在父
  3. 使用此构建器样式模式进行MongoDB查询

1 个答案:

答案 0 :(得分:8)

你正在与一生的问题发生冲突。

您的计划中有多个不同的生命周期:

  • type Object<'a> = BTreeMap<&'a str, i32>; =&gt;这是一个
  • &'a mut Object<'a> =&gt;这里最多有两个
  • struct Sub<'a>(&'a mut Object<'a>, &'a str); =&gt;这里最多有三个

显然,Object<'a>的引用没有理由与&str内的BTreeMap具有相同的生命周期。但是,您告诉编译器您希望两个生命周期都相同!

当你写:

struct Sub<'a>(&'a mut Object<'a>, &'a str);

你告诉编译器:

  • &strBTreeMap
  • 的生命周期
  • Object<'_>
  • 的引用的生命周期
  • &str
  • 附带的Object<'_>的有效期

都是一样的。

您对要求过度约束;因此,没有解决方案可以满足他们。

增加一个自由度就足够了!我们只会使Object<'_>的引用的生命周期与那些浮动的&str的生命周期不同:

struct Sub<'a, 'b: 'a>(&'a mut Object<'b>, &'b str);

impl<'b> Root<'b> {
    fn borrow_mut<'a>(&'a mut self, data: &'b str) -> Sub<'a, 'b> {
        Sub(&mut self.0, data)
    }

    fn borrow(&self) {
        println!("{:?}", self.0);
    }
}

请注意细微的'b: 'a

  • Object<'b>包含对其生命周期为'b
  • 的内容的引用
  • Object<'b>(表示为'a)的引用的生命周期必须比'b更短(否则你会引用死的东西?)

因此,我们说'b'a更长'b: 'a

就是这样。简单地放宽要求允许编译器允许您的代码进行编译。

请注意,一般情况下,如果您发现自己写的是&'a &'a str,那么您做错了。如果您考虑一下,您会意识到,为了创建对某事物的引用,它必须首先 。因此,对象必然的引用具有比对象本身更短的生命周期(稍微有点)。