1

I have an enumeration where multiple variants contain data I'd prefer not to clone. Occasionally, I want to switch between these variants, and not clone the data in them.

In essence, what I want to do is the following:

fn main() {
    let mut a = Data::One(DoNotClone {
        i: 1
    });

    move_data(&mut a);    
}

struct DoNotClone {
    i: usize
}

enum Data {
    One(DoNotClone),
    Two(DoNotClone)
}

fn move_data(data: &mut Data) {
    if let Data::One(donotclone) = data {
        // I cannot create Data::Two because I don't own donotclone here

        *data = Data::Two(donotclone)
    }    
}

This kind of operation isn't fundamentally impossible given ownership rules, but perhaps the borrow checker is unable to handle such a scenario.

I'd like to avoid using unsafe, or cloning the data. Is this possible?

Nathan Merrill
  • 7,648
  • 5
  • 37
  • 56
  • if you dont copy/clone, is not possible. At least the `i`, which is already copy, if this was just for the example then you will need to adapt your example. You will always need to do something of: own, copy/clone, some smart pointer which at the end you can clone... – Netwave Apr 11 '22 at 17:19
  • I was sure something like this had been asked before. I've VTC as duplicate – Nathan Merrill Apr 11 '22 at 17:21
  • "This kind of operation isn't fundamentally impossible given ownership rules, but perhaps the borrow checker is unable to handle such a scenario." -- you only have a `&mut Data`, how could you move out of it? – BallpointBen Apr 12 '22 at 02:25
  • @BallpointBen std::mem::replace lets you do just that. It's not impossible. Regardless, the other question and the associated rust RFC has a lot of discussion why something like this is problematic (e.g. panics) – Nathan Merrill Apr 12 '22 at 13:33

0 Answers0