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.
A mutable type is a type whose instance data can be modified. The System. Text. StringBuilder class is an example of a mutable reference type. It contains members that can change the value of an instance of the class.
Rust supports a concept, borrowing, where the ownership of a value is transferred temporarily to an entity and then returned to the original owner entity.
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();
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With