【问题标题】:How to tell the Rust compiler that a borrow has ended?如何告诉 Rust 编译器借用已经结束?
【发布时间】:2016-06-17 13:11:40
【问题描述】:

checking out tutorials 关于 Rust 时,我遇到了借用检查器的问题。以下代码无法编译:

struct Car {
    model: String,
}

struct Person<'a> {
    car: Option<&'a Car>,
}

impl<'a> Person<'a> {
    fn new() -> Person<'a> {
        Person { car: None }
    }

    fn buy_car(&mut self, c: &'a Car) {
        // how to say that Person don't borrow the old car any longer?
        self.car = Some(c);
    }
}

fn main() {
    let civic = Car { model: "Honda Civic".to_string() };
    let mut ghibli = Car { model: "Maserati Ghibli".to_string() };
    let mut bob = Person::new();

    bob.buy_car(&ghibli);

    bob.buy_car(&civic);

    // error: cannot borrow `ghibli` as mutable because it is also borrowed as immutable
    let anything = &mut ghibli;
}

我知道,由于其词法性质,Rust 的借用检查器无法识别 ghibli 的借用已经结束。

但我真的很想知道如何用 Rust 方式解决这个问题?我是否必须以某种方式使用Rc&lt;T&gt;Box&lt;T&gt;

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    告诉借用检查器借用结束的“Rust 方式”是引入一个新范围:

    fn main() {
        let civic = Car{model: "Honda Civic".to_string()};
        let mut ghibli = Car{model: "Maserati Ghibli".to_string()};
        {
            let mut bob = Person::new();
    
            bob.buy_car(&ghibli);
    
            bob.buy_car(&civic);
        }
        let anything = &mut ghibli;
    }
    

    您必须意识到,在您的示例中,(可能在大多数情况下)借用检查器是正确的。

    Bob 借用了ghibli 的引用。它仍然存在于他的 car 字段中的 main 方法的末尾。

    【讨论】:

    • 否:bob.buy_car(&amp;civic) 会覆盖 car 字段。所以借用检查器是“错误的”......虽然我认为它如此简单是正确的。
    • 啊。是的,当然,你是对的。一定忽略了这一点。
    • @MatthieuM。我的理解是借用检查器不查看内部方法,它只查看声明。考虑使用编译库中的方法,例如,没有可用的源代码。
    • @hamstergene:您的理解或多或少是正确的。借用检查器窥视enum/struct 内部(以推断他们是否借用/拥有)不会窥视内部函数,而仅使用它们的签名。这种简单性有两个好处:明确定义的边界(您可以在不破坏分析的情况下更改函数的内部结构)和实现的相对简单性(模拟函数的所有代码路径将是......地狱般的?) .尽管如此,我们仍然可以想象一些补充语法来指示替换语义等......我认为这不值得(这种情况太罕见了)。
    【解决方案2】:

    这是静态借用规则不起作用的情况,因为您无法告诉编译器的动态行为。

    您需要使用Rc&lt;T&gt;,它可以在运行时进行借用检查;或者,如果您需要可变访问权限,请使用 Rc&lt;Cell&lt;T&gt;&gt;Rc&lt;RefCell&lt;T&gt;&gt;。那么只要您以动态安全的方式访问它,一切都会好起来的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-08
      相关资源
      最近更新 更多