Search code examples
rusttraitsrefcell

Error borrowing content while rewriting a function to use traits


I'm new to Rust and toy with the language a little bit. I wrote two simple functions that increment and decrements a value inside Rc<RefCell<..>>. Since this functionality makes sense for any number type, I tried to turn them into generic functions:

use num::Integer;

// This works fine
pub fn increment_counter(c: &Rc<RefCell<u32>>) {
    let new_c = *c.borrow() + 1;
    c.replace(new_c);
}

// This does not compile
pub fn decrement_counter<T>(c: &Rc<RefCell<T>>)
where
    T: Integer,
{
    let new_c = *c.borrow() - T::one();
    c.replace(new_c);
}

I get this error suddenly:

55 |     let new_c = *c.borrow() - T::one();
   |                 ^^^^^^^^^^^ cannot move out of borrowed content

I don't understand why this change results in an error of this kind.


Solution

  • As far as I know, the u32 case works because u32 implements Copy, allowing to "move out of borrowed context" without problems. I.e. Copy tells that a type can be moved by simply copying the bits. Thus, it is no problem to move out of a borrowed value for this type.

    Thus, if you require Copy for the generic case, it should work, too.

    pub fn decrement_counter<T>(c: &Rc<RefCell<T>>)
    where
        T: Integer + Copy, // <- "Copy"
    {
        let new_c = *c.borrow();
        c.replace(new_c);
    }