How can I create a &mut MyEnum from &mut Nested?

Viewed 39

Let's say I have the following:

enum Item {
  None,
  Table(Table),
  ...
}

struct Table {
  ...
}

And let's say I have some table like this:

let t = &mut Table::new();

How would I go about upcasting t from a &mut Table into a &mut Item? If I try to convert directly like this:

let i = &mut Item::Table(t);

I get the error mismatched types expected struct Table, found &mut Table.

1 Answers

This is quite problematic.

If you don't need the same address, then you can wrap it in Item::Table. The problem is that you need to have an owned Table but you only have it borrowed. You can take it from there, but you need to leave something in its place so the reference is still valid. You can use std::mem::take() to put Default::default() inside or std::mem::replace() to put something else. You can also use the replace_with crate if you only need it temporarily.

let i = &mut Item::Table(std::mem::take(t));

let i = &mut Item::Table(std::mem::replace(t, Table::new()));

replace_with::replace_with_or_abort(t, |t| {
    let mut i = Item::Table(t);

    let i_ref = &mut i;
    // Work with `i_ref`...

    match i {
        Item::Table(t) => t,
        _ => unreachable!(),
    }
}

If you do need it to have the same address, then you're out of luck. Item does not have the same layout as Table, and so you cannot do that.

Related