0

Suppose I have the following code:

enum Foo {
    X { x: i32 },
    Y { y: String },
}

// Change x value if foo is X, otherwise do nothing.
fn test(foo: Rc<RefCell<Foo>>) {
    panic!("help!")
}

How do I implement test? I know I can implement it by adding a new method to Foo (either in impl Foo or as a trait) and using burrow_mut, like so:

impl Foo {
    pub fn go(&mut self) {
        match self {
            Foo::X { x } => *x = 3,
            _ => (),
        }
    }
}

fn test(foo: Rc<RefCell<Foo>>) {
    foo.borrow_mut().go()
}

I'm trying to come to grips with Rust's type system, so I was wondering if it's to implement something like this without a method, i.e., as a global function, or maybe even inline inside test itself.

For example, this doesn't work:

fn go(foo: &mut Foo) {
    match foo {
        Foo::X { x } => *x = 3,
        _ => (),
    }
}

fn test(foo: Rc<RefCell<Foo>>) {
    // mismatched types [E0308] expected `&mut Foo`, found `RefMut<Foo>`.
    go(foo.borrow_mut())
}

Full error:

error[E0308]: mismatched types
  --> src\main.rs:54:8
   |
54 |     go(foo.borrow_mut())
   |     -- ^^^^^^^^^^^^^^^^
   |     |  |
   |     |  expected `&mut Foo`, found struct `RefMut`
   |     |  help: consider mutably borrowing here: `&mut foo.borrow_mut()`
   |     arguments to this function are incorrect
   |
   = note: expected mutable reference `&mut Foo`
                         found struct `RefMut<'_, Foo>`

EDIT Solution from duplicate

Both of these work:

go(&mut *foo.borrow_mut());
    go(&mut foo.deref().borrow_mut());
    let x: &mut Foo = &mut foo.deref().borrow_mut();
    match x {
        Foo::X {x} => *x = 3,
        _ => (),
    }
Gal
  • 5,338
  • 5
  • 33
  • 55

0 Answers0