Hello everyone,
I would like to create a library that provides some access to another library. In other word, I create a Holder
struct that contains a V
struct on which I can apply some changes. I tried to keep the example below as simple as possible.
Since the V
struct is external to my crate, I assume I cannot do any change to its code. In practice, V
is a complex struct and cloning it comes at a large cost.
For the Holder
struct, methods can only take references to Holder
, not move objects. This restriction is very important.
Do you know if it is still possible to call V.add
without actually moving other: &Holder
inside the Holder.add
method?
Thanks!
use std::rc::Rc;
/// Some example struct I cannot directly edit
/// And that does not implement the Copy trait
#[derive(Debug)]
struct V {
value: i32,
}
impl V {
fn add(&mut self, other: Self) {
self.value += other.value;
}
}
/// Some struct I write
/// to store an inner struct V
#[derive(Debug)]
struct Holder {
value: Rc<V>,
}
impl Holder {
/// Function that calls V.add
/// Here, I can only references to Holder
/// either &Self or &mut Self
fn add(&mut self, other: &mut Self) {
// How to call V.add without cloning
// Holder.value, since it can cost a lot of time?
let other: V = Rc::try_unwrap(other.value).unwrap();
self.value.add(other); // This does not work, obviously
}
}
fn main() {
let mut v1 = V { value: 1 };
let mut v2 = V { value: 2 };
let mut h1 = Holder { value: Rc::new(v1) };
let mut h2 = Holder { value: Rc::new(v2) };
h1.add(&mut h2);
println!("h1: {:?}", h1);
println!("h2: {:?}", h2);
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `other.value` which is behind a mutable reference
--> src/main.rs:30:39
|
30 | let other: V = Rc::try_unwrap(other.value).unwrap();
| ^^^^^^^^^^^ move occurs because `other.value` has type `Rc<V>`, which does not implement the `Copy` trait
error[E0596]: cannot borrow data in an `Rc` as mutable
--> src/main.rs:31:9
|
31 | self.value.add(other); // This does not work, obviously
| ^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc<V>`
warning: variable does not need to be mutable
--> src/main.rs:36:9
|
36 | let mut v1 = V { value: 1 };
| ----^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: variable does not need to be mutable
--> src/main.rs:37:9
|
37 | let mut v2 = V { value: 2 };
| ----^^
| |
| help: remove this `mut`
Some errors have detailed explanations: E0507, E0596.
For more information about an error, try `rustc --explain E0507`.
warning: `playground` (bin "playground") generated 2 warnings
error: could not compile `playground` due to 2 previous errors; 2 warnings emitted