Help needed to understand below code

code - 1

#[derive(Debug)]
enum Bar {
  FooBar(i32),
  BarFoo(String),
}

fn foo(i:Bar, j:&mut Bar) {
  match j {
     Bar::FooBar(_) => println!("{:?}",j),
    _=>()
  }
}

code -2

#[derive(Debug)]
enum Bar {
  FooBar(i32),
  BarFoo(String),
}
fn foo(i:Bar, j:&mut Bar) {
  match (i,j) {
    (_, Bar::BarFoo(_)) => println!("{:?}",j),
    _=>()
  }
}

code -1 runs without any error but for code-2 I'm getting below error.

  Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of moved value: `j`
 --> src/lib.rs:8:44
  |
6 | fn foo(i:Bar, j:&mut Bar) {
  |               - move occurs because `j` has type `&mut Bar`, which does not implement the `Copy` trait
7 |   match (i,j) {
  |            - value moved here
8 |     (_, Bar::BarFoo(_)) => println!("{:?}",j),
  |                                            ^ value borrowed here after move
  |

Please Ignore the logic in the code.
What exactly causing the error in code -2 ?. Only difference between code-1 & code-2 is that in code-2 I'm using a tuple in match case. How this causing the issue of 'move' when similar code is working in the case of code-1. or am i wrong ? please help to understand what's happening here

You are moving the mutable / exclusive reference j in order to construct something else, a tuple with the type (Bar, &mut Bar). Since &mut references are not Copy, the previous binding is invalidated.
Note that you could "reborrow":

#[derive(Debug)]
enum Bar {
    FooBar(i32),
    BarFoo(String),
}

fn foo(i: Bar, j: &mut Bar) {
    match (i, &mut *j) { // <- deref and borrow again
        (_, Bar::BarFoo(_)) => println!("{:?}", j),
        _ => (),
    }
}

This compiles.

Note that when calling functions, the compiler will automatically reborrow for you, in order to keep &mut T ergonomic: Copy and reborrows - Learning Rust

2 Likes

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.