Cannot borrow data in a dereference of `RefMut<'_, &Atom>` as mutable

Hi there!

I have a type like this:

pub struct AtomWithHierarchyMut<'a> {
    /// The Chain containing this Atom
    pub chain: &'a Chain,
    /// The Residue containing this Atom
    pub residue: &'a Residue,
    /// The Conformer containing this Atom
    pub conformer: &'a Conformer,
    /// This Atom
    pub atom: RefCell<&'a Atom>,
}

and I want to mutate the atom field in place. The Atom struct in turn looks like this:

pub struct Atom {
    ...
    /// The occupancy of the Atom
    occupancy: f64,
    ...

}

And what I tried then is:

let atom_hi_mut = AtomWithHierarchyMut::new(chain, residue, conformer, RefCell::new(atom));
let mut atom_mut = atom_hi_mut.atom.borrow_mut();
// This method mutates the `occupancy` field.
atom_mut.set_occupancy(1.00)?;

But I get this error message:
cannot borrow data in a dereference of RefMut<', &Atom>as mutable traitDerefMutis required to modify through a dereference, but it is not implemented forRefMut<', &Atom>``

I'm still trying to wrap my head around how RefCell works and how I can use it to mutate stuff and it was my impression that I can use it for a case like this but I don't quite understand the error message. Do I need to implement DerefMut for Atom or does this hint at something else?

The RefCell will let you go from &AtomWithHierarchyMut to &mut &Atom, but you need an &mut Atom to modify the Atom. Unfortunately, flattening the double reference &mut &Atom results in an &Atom as one of the two references is immutable.

Note: When reading this, pay close attention to the order and number of ampersands.

Maybe you wanted &'a RefCell<Atom>?

So RefCell will not let me mutate anything inside if it's behind a reference, yes? I think that's the key of my misunderstanding here.

Indeed. A RefCell lets you go from &RefCell<T> to &mut T, but in your case the reference and cell is reversed.

Ok, thanks for clarifying! I'll have to rethink my approach.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.