I'm using this struct:
pub struct Store {
pub player: HashMap<i64, Player>,
pub team: HashMap<i64, Team>,
}
impl Store {
pub fn new() -> Arc<Self> {
Arc::new(Self {
player: HashMap::new(),
team: HashMap::new(),
})
}
}
sharing it in my resolvers with:
async fn player_by_id(&self, store: Arc<Store>, id: i64) -> Result<()> {
let team = get_team();
store.team.insert(id, team.into()); // here I get the error
}
I get the error:
error[E0596]: cannot borrow data in an `Arc` as mutable
|
84 | store.team.insert(id, team.into());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<Store>`
Why?
As explained in Rc's documentation,
Shared references in Rust disallow mutation by default, and Rc is no exception: you cannot generally obtain a mutable reference to something inside an Rc.
Arc is the same as Rc in this regard. You need to use a Mutex or RwLock
(or atomics) to change its contents.
Related
I created two structs, Car and CarModifier. Both Car and CarModifier are instantiated in main.rs. CarModifier modifies one of the fields of Car using data from curl request. Here is the code:
main.rs
use sample::{car::Car, car_modifier::CarModifier};
fn main() {
println!("Hello, world!");
let mut car = Car::new();
let mut car_modifier = CarModifier::new();
car_modifier.update_car(&mut car);
println!("{:?}", car.driver);
}
Car.rs
#[derive(Debug)]
pub struct Car<'a> {
pub driver: &'a [u8]
}
impl<'a> Car<'a> {
pub fn new() -> Self {
Self {
driver: &[26]
}
}
pub fn update_driver(&mut self, new_driver: &'a [u8]) {
self.driver = new_driver;
}
}
CarModifier.rs
use curl::easy::Easy;
use crate::{car::Car};
pub struct CarModifier;
impl CarModifier {
pub fn new() -> Self {
Self {
}
}
pub fn update_car(&mut self, car: &mut Car) {
let mut easy = Easy::new();
easy.url("https://www.rust-lang.org/").unwrap();
let mut transfer = easy.transfer();
transfer.write_function(|data: &[u8]| {
car.update_driver(data);
Ok(data.len())
}).unwrap();
transfer.perform().unwrap();
}
}
This is the error which I get when trying to run
error[E0521]: borrowed data escapes outside of closure
--> src/car_modifier.rs:19:13
|
13 | pub fn update_car(&mut self, car: &mut Car) {
| --- `car` declared here, outside of the closure body
...
18 | transfer.write_function(|data: &[u8]| {
| ---- `data` is a reference that is only valid in the closure body
19 | car.update_driver(data);
| ^^^^^^^^^^^^^^^^^^^^^^^ `data` escapes the closure body here
For more information about this error, try `rustc --explain E0521`.
error: could not compile `sample` due to previous error
I seem to understand from the error that data lives only in the closure body and the code tries to refer that in car.driver which will outlive the closure body, hence the error. Is this the right understanding?
I am also aware that instead of using &[u8], I could use Vec<u8> to resolve the error. But how can I keep using &[u8]?
Basically data belongs to the curl library. It may be a slice of some library internal buffer pool, and may be re-used for some other curl api calls later on, or freed after this call. You need to copy data into the Car structure instead of just having a pointer to the underlying buffer. Rust compiler helps you to catch that problem. In C++ the compiler won't even tell you this error and the C++ code will have runtime problems.
So, I have the following problem. I have a structure implementation, and one of the methods of this structure consumes the instance of the structure, which is ok by me, as it is literally the last thing I want to do in my program with this instance (my_struct), but it's totally not OK with the borrow checker:
use std::thread;
struct MyStruct {
some_field: Vec<String>
}
impl MyStruct {
fn new() -> Self {
MyStruct {
some_field: vec!("str".to_string())
}
}
fn do_something_with_self_in_thread(&'static mut self) {
thread::spawn(move || self.some_field = vec!("another_str".to_string()));
}
}
fn main() {
let my_struct: &'static mut MyStruct = &mut MyStruct::new();
my_struct.do_something_with_self_in_thread()
// Some blocking call will follow
}
Error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:20:49
|
20 | let my_struct: &'static mut MyStruct = &mut MyStruct::new();
| --------------------- ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
21 | my_struct.do_something_with_self_in_thread()
22 | }
| - temporary value is freed at the end of this statement
For more information about this error, try `rustc --explain E0716`.
I tried playing around with lifetimes, but resultless.
How do I get myself out of this situation?
Playground link
When we say a method consumes the instance, then it should take self and not a mutable borrow &mut self in the definition.
i.e.
impl MyStruct {
...
fn do_something_with_self_in_thread(self) {
...
}
}
As commenters have already said, your second problem is with lifetimes. The compiler can't reason about references not outliving owners of resources if they are in separate threads. So to this end the thread::spawn method has trait bounds requiring that the closure is 'static, which means the variables it captures can live as long as they like. Examples which are valid would be owned types T, not references &T or &mut T, unless they are &'static T types. That's not the case in your code as you've instantiated a struct inside main (albeit erroneously annotated as having a 'static lifetime) and then tried to move a mutable borrow of a field inside your closure.
This question already has an answer here:
Linking the lifetimes of self and a reference in method
(1 answer)
Closed 2 years ago.
I have been working on a simple lexer in rust. However, I have ran into the error[E0502]: cannot borrow 'a_rule' as immutable because it is also borrowed as mutable problem. I have checked other answers and I can't seem to find the reason.
pub struct Rule<'a> {
selector: &'a str,
}
impl<'a> Rule<'a> {
pub fn new(selector: &'a str) -> Self {
Self {
selector
}
}
pub fn get_selector(&'a self) -> &'a str {
self.selector
}
pub fn set_selector(&'a mut self, selector: &'a str) {
self.selector = selector
}
}
#[cfg(test)]
mod tests {
use super::Rule;
#[test]
fn set_selector_test() {
let mut a_rule = Rule::new(".foo");
a_rule.set_selector(".bar");
assert_eq!(a_rule.get_selector(), ".bar")
}
}
Error:
error[E0502]: cannot borrow `a_rule` as immutable because it is also borrowed as mutable
--> src/lib.rs:30:20
|
28 | a_rule.set_selector(".bar");
| ------ mutable borrow occurs here
29 |
30 | assert_eq!(a_rule.get_selector(), ".bar")
| ^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
(Playground)
I would also like to use the opportunity to ask if it is recommended or not to use java like get and set methods or just set the members within a struct as public.
Please feel free to call out any other dumb mistakes.
You’ve tied the lifetime of your rule to the lifetime of your string by making get_selector and set_selector take &'a self/&'a mut self, but that’s not the correct relationship between them. You can produce &'a strs without needing your self to live that long (or be borrowed mutably for that long) because self.selector is already an &'a str.
Remove the 'a on the self references:
pub fn get_selector(&self) -> &'a str {
self.selector
}
pub fn set_selector(&mut self, selector: &'a str) {
self.selector = selector;
}
(but do you need this getter and setter at all? consider immutability!)
I have a struct that has inner mutability.
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
Produces the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
The problem is that I can't have a function on Foo that returns a borrowed vec, because the borrowed vec is only valid for the lifetime of the Ref, but the Ref goes out of scope immediately.
I think the Ref must stick around because:
RefCell<T> uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because RefCell<T> borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in task panic.
Now I could instead write a function like this that returns the entire interior:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
However this potentially exposes fields (MutableInterior.hide_me in this example) that are really private implementation details to Foo.
Ideally I just want to expose the vec itself, potentially with a guard to implement the dynamic borrowing behavior. Then callers do not have to find out about hide_me.
Instead of creating a brand new type, you can use Ref::map (since Rust 1.8). This has the same result as Levans' existing answer:
use std::cell::Ref;
impl Foo {
pub fn get_items(&self) -> Ref<'_, Vec<i32>> {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can also use new features like impl Trait to hide the Ref from the API:
use std::cell::Ref;
use std::ops::Deref;
impl Foo {
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_ {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can create a new struct similar to the Ref<'a,T> guard returned by RefCell::borrow(), in order to wrap this Ref and avoid having it going out of scope, like this:
use std::cell::Ref;
struct FooGuard<'a> {
guard: Ref<'a, MutableInterior>,
}
then, you can implement the Deref trait for it, so that it can be used as if it was a &Vec<i32>:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b> {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> {
&self.guard.vec
}
}
after that, update your get_items() method to return a FooGuard instance:
impl Foo {
pub fn get_items(&self) -> FooGuard {
FooGuard {
guard: self.interior.borrow(),
}
}
}
and Deref does the magic:
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
}
You can wrap the Vec in an Rc.
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior {
hide_me: i32,
vec: Rc<Vec<i32>>,
}
struct Foo {
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> Rc<Vec<i32>> {
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Rc::new(Vec::new()),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
When you need to mutate the Vec, use Rc::make_mut to obtain a mutable reference to the Vec. If there are still other Rcs referring to the Vec, make_mut will dissociate the Rc from the other Rcs, clone the Vec and update itself to refer to that new Vec, then give you a mutable reference to it. This ensures that the value in the other Rcs doesn't suddenly change (because Rc by itself doesn't provide interior mutability).
I have a struct that has inner mutability.
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
Produces the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
The problem is that I can't have a function on Foo that returns a borrowed vec, because the borrowed vec is only valid for the lifetime of the Ref, but the Ref goes out of scope immediately.
I think the Ref must stick around because:
RefCell<T> uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because RefCell<T> borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in task panic.
Now I could instead write a function like this that returns the entire interior:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
However this potentially exposes fields (MutableInterior.hide_me in this example) that are really private implementation details to Foo.
Ideally I just want to expose the vec itself, potentially with a guard to implement the dynamic borrowing behavior. Then callers do not have to find out about hide_me.
Instead of creating a brand new type, you can use Ref::map (since Rust 1.8). This has the same result as Levans' existing answer:
use std::cell::Ref;
impl Foo {
pub fn get_items(&self) -> Ref<'_, Vec<i32>> {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can also use new features like impl Trait to hide the Ref from the API:
use std::cell::Ref;
use std::ops::Deref;
impl Foo {
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_ {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can create a new struct similar to the Ref<'a,T> guard returned by RefCell::borrow(), in order to wrap this Ref and avoid having it going out of scope, like this:
use std::cell::Ref;
struct FooGuard<'a> {
guard: Ref<'a, MutableInterior>,
}
then, you can implement the Deref trait for it, so that it can be used as if it was a &Vec<i32>:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b> {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> {
&self.guard.vec
}
}
after that, update your get_items() method to return a FooGuard instance:
impl Foo {
pub fn get_items(&self) -> FooGuard {
FooGuard {
guard: self.interior.borrow(),
}
}
}
and Deref does the magic:
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
}
You can wrap the Vec in an Rc.
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior {
hide_me: i32,
vec: Rc<Vec<i32>>,
}
struct Foo {
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> Rc<Vec<i32>> {
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Rc::new(Vec::new()),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
When you need to mutate the Vec, use Rc::make_mut to obtain a mutable reference to the Vec. If there are still other Rcs referring to the Vec, make_mut will dissociate the Rc from the other Rcs, clone the Vec and update itself to refer to that new Vec, then give you a mutable reference to it. This ensures that the value in the other Rcs doesn't suddenly change (because Rc by itself doesn't provide interior mutability).