Matching on `&mut self` without moving it


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


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 {

enum MyTypeConf {

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/
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) {

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.