6

I have a function of a third party library that needs ownership of a variable. Unfortunately this variable is inside a Rc<RefCell<Option<Foo>>>.

My code looks simplified like this:

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

pub struct Foo {
    val: i32,
}

fn main() {
    let foo: Rc<RefCell<Option<Foo>>> = Rc::new(RefCell::new(Some(Foo { val: 1 })));

    if let Some(f) = foo.into_inner() {
        consume_foo(f);
    }
}

fn consume_foo(f: Foo) {
    println!("Foo {} consumed", f.val)
}
error[E0507]: cannot move out of an `Rc`
  --> src/main.rs:11:22
   |
11 |     if let Some(f) = foo.into_inner() {
   |                      ^^^ move occurs because value has type `std::cell::RefCell<std::option::Option<Foo>>`, which does not implement the `Copy` trait

I tried to use std::mem::replace(...) from How can I swap in a new value for a field in a mutable reference to a structure?:

fn main() {
    let mut foo: Rc<RefCell<Option<Foo>>> = Rc::new(RefCell::new(Some(Foo { val: 1 })));

    let mut foo_replaced = std::mem::replace(&mut foo.into_inner(), None);
    if let Some(f) = foo_replaced.take() {
        consume_foo(f);
    }
}
error[E0507]: cannot move out of an `Rc`
  --> src/main.rs:11:51
   |
11 |     let mut foo_replaced = std::mem::replace(&mut foo.into_inner(), None);
   |                                                   ^^^ move occurs because value has type `std::cell::RefCell<std::option::Option<Foo>>`, which does not implement the `Copy` trait

I can't figure out how to do this properly.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Natjo
  • 2,005
  • 29
  • 75
  • 1
    It looks like your question might be answered by the answers of [How do I move out of a struct field that is an Option?](https://stackoverflow.com/q/52031002/155423); [How can I swap in a new value for a field in a mutable reference to a structure?](https://stackoverflow.com/q/27098694/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Oct 14 '19 at 20:00
  • 1
    `let foo = foo.borrow_mut().take(); if let Some(f) = foo {` – Shepmaster Oct 14 '19 at 20:17
  • 1
    Your last idea worked! Thank you very much :) – Natjo Oct 14 '19 at 20:25

0 Answers0