cannot borrow as immutable because it is also borrowed as mutable

ⅰ亾dé卋堺 提交于 2020-01-11 02:42:11

问题


I'm using the structs Foo and Bar from a library and I'm getting a compilation error in the client code. I simplified the code to this:

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)

Output:

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

The error in the console output is very clear, but I cannot fix the problem.


回答1:


You can limit the lifetime of the array variable by placing it in a new scope with curly braces ({ ... }):

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



回答2:


You original code will work as-is once non-lexical lifetimes are enabled by default:

#![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();
}

With NLL, the borrow checker becomes more advanced and precise; it can now understand that you aren't using array after the call to process so it is safe to use foo in a new manner.



来源:https://stackoverflow.com/questions/35054404/cannot-borrow-as-immutable-because-it-is-also-borrowed-as-mutable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!