0

I want to do as follows, but columns is moved in both and_modify and or_insert (which we know are mutually exclusive), but the compiler will not allow it. Is there a way to still use the Entry API, or should I refactor to something like match self.tables.get(&table_name), which the compiler will understand are mutually exclusive branches?

self.tables.entry(table_name)
           .and_modify(|e| e.columns = Some(columns))
           .or_insert(TableInfo{
               policies: None,
               columns: Some(columns),
           });
jonathanGB
  • 1,500
  • 2
  • 16
  • 28
  • Please modify your code to contain a [mre]? It's easier for people to answer when the code is complete. – trent Apr 03 '20 at 20:50
  • Related: [How to move data into multiple Rust closures?](https://stackoverflow.com/q/52464653/3650362) – trent Apr 03 '20 at 21:32

1 Answers1

3

Since or_insert() returns a mutable reference to the value – either the existing one or the newly inserted one – you should be able to insert None for columns in the new entry, and then unconditionally overwrite it with Some(columns):

self.tables
    .entry(table_name)
    .or_insert(TableInfo {
        policies: None,
        columns: None,
    })
    .columns = Some(columns);

A different, somewhat more generic solution is to wrap columns in an Option first, and then use Option::take() in the two mutually exclusive closures:

let mut columns = Some(columns);
self.tables
    .entry(table_name)
    .and_modify(|t| t.columns = columns.take())
    .or_insert_with(|| TableInfo {
        policy: None,
        columns: columns.take(),
    });

Only one of the two closures will actually be able to extract the original value, but we know that exactly one will be executed, so this is fine. (I replaced or_insert() with or_insert_with(), so we actually have two closures, only one of which is executed. This isn't strictly necessary to make this approach work but I think it makes it clearer.)

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8d86c4e26b3b1e06ea31fda58ca7782a – Skgland Apr 03 '20 at 20:50