-1

First of all, I am sorry for that I cannot compare some duplicate questions to mine because I am a beginner in Rust. Possibly duplicate question

The compiler outputs an error for my code as:

error[E0507]: cannot move out of index of `std::vec::Vec<std::rc::Rc<dyn T>>`
  --> src/lib.rs:30:18
   |
30 |     let V_last = data.V[V_lastIdx];
   |                  ^^^^^^^^^^^^^^^^^
   |                  |
   |                  move occurs because value has type `std::rc::Rc<dyn T>`, which does not implement the `Copy` trait
   |                  help: consider borrowing here: `&data.V[V_lastIdx]`

Please help me to solve problem.

use std::collections::HashMap;
use std::rc::Rc;

trait T {
    fn main(&self, data: &mut Data) -> ();
}

#[derive(Clone)]
struct S1 {
    val: usize,
    t: Rc<dyn T>,
}

struct S2 {
    val: usize,
}

impl T for S1 {
    fn main(&self, data: &mut Data) -> () {
        data.V.push(Rc::new(S2 { val: 123 }));
    }
}

impl T for S2 {
    fn main(&self, data: &mut Data) -> () {}
}

struct Data {
    // Up to 1 instance which may hold about 30MB at most.
    V: Vec<Rc<dyn T>>,
    name_match: HashMap<String, (usize, usize)>,
}

fn round(data: &mut Data) {
    let V_lastIdx = data.V.len() - 1;
    let V_last = data.V[V_lastIdx];
    return V_last.main(data);
}

After I followed the compiler suggestion, a new error says as follows.

 help: consider borrowing here: `&data.V[V_lastIdx]`
error[E0502]: cannot borrow `*data` as mutable because it is also borrowed as immutable
  --> src/lib.rs:34:11
let V_last= &data.V[V_lastIdx];   
   |                 ------ immutable borrow occurs here
34 |    return V_last.main(data);
   |           ^^^^^^^----^^^^^^
   |           |      |
   |           |      immutable borrow later used by call
   |           mutable borrow occurs here

Playground

Now I have selected the answer, I notice that my original code could be more simple as following link, with the solution code borrowed from the selected answer.

Playground

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
skatori
  • 547
  • 6
  • 20
  • read the compile error, do what it already tell you, then [edit] your question then close it as duplicate of https://stackoverflow.com/questions/57017747/why-does-refactoring-by-extracting-a-method-trigger-a-borrow-checker-error/57018038#57018038 – Stargateur Nov 07 '20 at 15:49
  • @Stargateur, Please explain how they are duplicate. – skatori Nov 07 '20 at 16:01
  • @Stargateur, Can't you see that if the two are really so duplicate, my question is more valuable because my question is clearly shorter and simpler than your link. your link contains too many information and complicated. – skatori Nov 07 '20 at 16:13
  • Have you tried doing what the compiler's message suggests that you do? – user4815162342 Nov 07 '20 at 16:17
  • fwiw, stargateur's link does a good job of explaining why the compiler's suggestion doesn't work (addressing `fn func(&mut Parent, &Child)`-type patterns), though I agree the Q&A is not particularly easy for a newcomer to understand and apply, since the suggested fix is pretty specific and not the only workaround. – kmdreko Nov 07 '20 at 18:47

2 Answers2

2

When you do some_vec[index], it will try to move the element out of the vec, but that is not allowed. One fix, as provided by the compiler, is to borrow the element instead: &some_vec[index]. However, the compiler rejects that solution, as well it should, because if allowed the call to main with self as a reference to an element in data would/could be invalidated by the .push call.

Another fix, as demonstrated in your self-answer, is require cloning the vec V so that they have different ownership and therefore the references can't be invalidated.

A better solution is to clone the element and not the whole vector. A particularly reasonable solution given that your elements are Rcs and therefore cheap to clone:

fn round(data: &mut Data) {
    let V_lastIdx = data.V.len() - 1;
    let V_last = data.V[V_lastIdx].clone();
                               // ^^^^^^^^
    return V_last.main(data);
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106
0

Reading the accepted answer, I realized that my solution below was not a good idea at all for my purpose.

I solved the error myself as follows by editing the round function.

Before:

fn round(data: &mut Data) {
   let V_lastIdx = data.V.len() - 1;
   let V_last= &data.V[V_lastIdx];   
   V_last.main(data)
}

After:

Playground

fn round(V: Vec<Rc<T>>, data: &mut Data) {
   let V_lastIdx = V.len() - 1;
   let V_last = &V[V_lastIdx];   
   V_last.main(data)
}
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
skatori
  • 547
  • 6
  • 20