Matching on `&mut self` without moving it

Hello,

I'm stumbling over a seemingly very simply borrowchecker issue:

#![allow(unused_variables)]

pub struct A;
pub struct B;
pub struct AConf;
pub struct BConf;

impl A {
    pub fn new(conf: AConf) -> Self { A }
    pub fn update_conf(&mut self, conf: AConf) {}
}

impl B {
    pub fn new(conf: BConf) -> Self { B }
    pub fn update_conf(&mut self, conf: BConf) {}
}

enum MyType {
    A(A),
    B(B),
}

enum MyTypeConf {
    A(AConf),
    B(BConf),
}

impl MyType {
    fn update_conf(&mut self, conf: MyTypeConf) {
        match (self, conf) {
            (MyType::A(a), MyTypeConf::A(a_conf)) => a.update_conf(a_conf),
            (MyType::B(b), MyTypeConf::B(b_conf)) => b.update_conf(b_conf),
            (MyType::A(_), MyTypeConf::B(b_conf)) => *self = MyType::B(B::new(b_conf)),
            (MyType::B(_), MyTypeConf::A(a_conf)) => *self = MyType::A(A::new(a_conf))
        }
    }
}

This fails to compile, because match (self, conf) moves self, so I cannot dereference it later. The problem is if I try to match on &self, I cannot take a mutable reference to the content of MyType, in the first two branches of the match... Is there a clever way to make the borrow checker understand my intent here?

Link to the playgorund: Rust Playground

And the error:

error[E0382]: use of moved value: `self`
  --> src/lib.rs:33:54
   |
29 |     fn update_conf(&mut self, conf: MyTypeConf) {
   |                    --------- move occurs because `self` has type `&mut MyType`, which does not implement the `Copy` trait
30 |         match (self, conf) {
   |                ---- value moved here
...
33 |             (MyType::A(_), MyTypeConf::B(b_conf)) => *self = MyType::B(B::new(b_conf)),
   |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value used here after move

You can explicitly reborrow self in the match:

 match (&mut *self, conf) {
5 Likes