不能借用不可变的因为它也被借用为可变的

时间:2016-01-28 06:38:23

标签: rust

我正在使用库中的结构FooBar,并且我在客户端代码中收到了编译错误。我将代码简化为:

use std::marker::PhantomData;

struct Foo {
    some_str: &'static str,
}

struct Bar<'a> {
    some_str: &'static str,
    marker: PhantomData<&'a Foo>,
}

impl Foo {
    fn read_data(&self) {
        // add code here
    }
    fn create_bar<'a>(&'a mut self) -> Bar<'a> {
        Bar {
            some_str: "test2",
            marker: PhantomData,
        }
    }
}

fn process(_arr: &mut [Bar]) {}

fn main() {
    let mut foo = Foo { some_str: "test" };
    let mut array: [Bar; 1] = [foo.create_bar()];
    process(&mut array);
    foo.read_data();
}

playground

输出:

error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
  --> src/main.rs:30:5
   |
28 |     let mut array: [Bar; 1] = [foo.create_bar()];
   |                                --- mutable borrow occurs here
29 |     process(&mut array);
30 |     foo.read_data();
   |     ^^^ immutable borrow occurs here
31 | }
   | - mutable borrow ends here

控制台输出中的错误非常清楚,但我无法解决问题。

2 个答案:

答案 0 :(得分:4)

您可以通过将array变量置于带有大括号({ ... })的新范围来限制其生命周期:

fn main() {
    let mut foo = Foo { some_str: "test" };
    {
        let mut array: [Bar; 1] = [foo.create_bar()];
        process(&mut array);
    }
    foo.read_data();
}

答案 1 :(得分:3)

默认情况下,一旦启用non-lexical lifetimes,您的原始代码将按原样工作:

#![feature(nll)]

use std::marker::PhantomData;

struct Foo {
    some_str: &'static str,
}

struct Bar<'a> {
    some_str: &'static str,
    marker: PhantomData<&'a Foo>,
}

impl Foo {
    fn read_data(&self) {
        // add code here
    }
    fn create_bar<'a>(&'a mut self) -> Bar<'a> {
        Bar {
            some_str: "test2",
            marker: PhantomData,
        }
    }
}

fn process(_arr: &mut [Bar]) {}

fn main() {
    let mut foo = Foo { some_str: "test" };
    let mut array: [Bar; 1] = [foo.create_bar()];
    process(&mut array);
    foo.read_data();
}

使用NLL,借阅检查器变得更加先进和精确;现在可以了解到,在调用array之后您没有使用process,因此可以安全地以新方式使用foo