Warm tip: This article is reproduced from serverfault.com, please click

move occurs because value has type `RefCell`, which does not implement the `Copy` trait

发布于 2020-11-28 04:28:17

UPDATE My real problem was caused by my IDE having auto-imported use std::borrow::{Borrow, BorrowMut};. With this line, the accepted answer also doesn't compile. The solution was removing the line.


I'm getting the following error message:

15 |     instance_context.into_inner().instances = Some(vec![String::from("abc")]);
   |     ^^^^^^^^^^^^^^^^ move occurs because value has type `RefCell<InstanceContext>`, which does not implement the `Copy` trait

and I have no idea why, or how to fix the code.

Playground:

#![allow(dead_code)]
#![allow(unused_variables)]

use std::rc::Rc;
use std::cell::RefCell;

struct InstanceContext {
    id: i32,
    instances: Option<Vec<String>>,
}

fn main() {
    let instance_context = Rc::new(RefCell::new(InstanceContext { id: 5, instances: None }));
    // clojures are created that use instance_context, which does not yet have 'instances' set
    instance_context.into_inner().instances = Some(vec![String::from("abc")]);
}
Questioner
xoa991x
Viewed
0
Mihir 2020-11-28 13:25:47

into_inner() method will consume the RefCell instance to give you the wrapped value.

To achieve that, it requires you to have ownership over the instance of RefCell. But you don't have that as it is within Rc and unless you consume the Rc as well to get ownership of RefCell, you can't call into_inner().


In your code, due to deref coersion, you get immutable ref to the inside RefCell so you can only call methods that accept &self.

If you want mutate the contents inside RefCell, you can do it as follows:

#![allow(dead_code)]
#![allow(unused_variables)]

use std::rc::Rc;
use std::cell::RefCell;

struct InstanceContext {
    id: i32,
    instances: Option<Vec<String>>,
}

fn main() {
    let instance_context = Rc::new(RefCell::new(InstanceContext { id: 5, instances: None }));
    instance_context.borrow_mut().instances = Some(vec![String::from("abc")]);
}

Playground

borrow_mut() takes an immutable ref to RefCell instance and lets you get a mutable ref to the wrapped value with which you can mutate the contents of the wrapped value.