Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have mutable binding and destructuring simultaneously?

The folllowing code works as expected (demo) but this requires two nested match {} which I want to replace with just one.

#![allow(unused)]
use std::collections::hash_map::HashMap;

#[derive(Debug, Clone)]
struct NormalTransaction(f64);

//  only normal transaction can be disputed.. BY DESIGN
#[derive(Debug, Clone)]
struct DisputeTransaction(NormalTransaction);

#[derive(Debug, Clone)]
enum Transaction {
    Normal(NormalTransaction),
    Dispute(DisputeTransaction),
}

fn main() {
    let mut m = HashMap::new();
    m.insert(1, Transaction::Normal(NormalTransaction(100.0)));
    
    println!("before: {:#?}", m);
    
    match m.get_mut(&1) {
        Some(t) => match t {
            Transaction::Normal(normal) => {
                *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
            }   
            _ => {}, // NA
        }
        _ => {}, // NA
    }
    
    println!("after: {:#?}", m);
}

Replacing the two match{} with just one, as follows:

    match m.get_mut(&1) {
        Some(t @ Transaction::Normal(normal)) => {
            *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
        }
        _ => {}, // NA
    }

but it does not work, saying (demo):

error: borrow of moved value
  --> src/main.rs:24:14
   |
24 |         Some(t @ Transaction::Normal(normal)) => {
   |              -^^^^^^^^^^^^^^^^^^^^^^^------^
   |              |                       |
   |              |                       value borrowed here after move
   |              value moved into `t` here
   |              move occurs because `t` has type `&mut Transaction` which does not implement the `Copy` trait

error[E0382]: borrow of moved value
  --> src/main.rs:24:38
   |
24 |         Some(t @ Transaction::Normal(normal)) => {
   |              ------------------------^^^^^^-
   |              |                       |
   |              |                       value borrowed here after move
   |              value moved here
   |
   = note: move occurs because value has type `&mut Transaction`, which does not implement the `Copy` trait
help: borrow this field in the pattern to avoid moving the value
   |
24 |         Some(ref t @ Transaction::Normal(normal)) => {
   |              +++

Is it possible to do the mutable binding and destructuring in single match case?

like image 420
Nawaz Avatar asked Oct 24 '25 15:10

Nawaz


1 Answers

I don't know of a way to do it using a single match, but it doesn't look that bad if you use if lets instead of matches:

if let Some(t) = m.get_mut(&1) {
    if let Transaction::Normal(normal) = t {
        *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
    }   
}

Once let-chains lands I believe you should also be able to write

if let Some(t) = m.get_mut(&1) && let Transaction::Normal(normal) = t {
    *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
}
like image 163
orlp Avatar answered Oct 26 '25 05:10

orlp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!