Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing a enum's field in Rust

Tags:

oop

enums

rust

I am very new to Rust but I am trying to work out how to modify an instance of an enum. I need to use managed boxes for other reasons, but it seems to make changing an enum's field hard.

#[feature(managed_boxes)];

enum State { A(int), B }

fn main() {
    let mut state = @A(123);

    match *state {
         A(ref mut i)  => { *i = 456 }
         B => { }
    }
    println!("{:?}", state)
}

I get the error cannot borrow immutable anonymous field as mutable. The mut seems to only say that state, the variable, is mutable. I want to tell Rust the whole thing is mutable. I find forced immutability one of the most annoying things of Rust.

like image 350
user3074414 Avatar asked Oct 27 '25 05:10

user3074414


1 Answers

Some time ago managed boxed had their own "hierarchy" of mutability. The following code used to work then:

#[feature(managed_boxes)];

enum State { A(int), B }

fn main() {
    let state = @mut A(123);

    match *state {
         A(ref mut i)  => { *i = 456 }
         B => { }
    }
    println!("{:?}", state)
}

But managed boxes are scheduled to be removed from the language. In current version of Rust @mut is not a valid token. You have to use RefCell, a mutable cell which provides mutability inside managed pointers. Currently it looks somewhat like this:

#[feature(managed_boxes)];
use std::cell::RefCell;

enum State { A(int), B }

fn main() {
    let state = @RefCell::new(A(123));

    {
        let mut r = state.borrow_mut();
        match r.get() {
            &A(ref mut i)  => { *i = 456 }
            &B => { }
        }
    }

    println!("{:?}", state)
}

You will get rather extensive output on the terminal though, because it will print internals of RefCell structure. See documentation on std::cell module for more information on cells and how to use them.

In the future Rust won't have special syntax for managed boxes at all. Garbage collection will be implemented in libraries. I believe the code will look like this (Rust authors, please correct me if I'm wrong):

use std::cell::RefCell;

enum State { A(int), B }

fn main() {
    // state is of type Gc<RefCell<State>>
    let state = box(Gc) RefCell::new(A(123));

    // Dereference will work for library pointer types, not sure about autodereference
    let mut r = (*state).borrow_mut();
    match r.get() {
        &A(ref mut i)  => { *i = 456 }
        &B => { }
    }

    println!("{:?}", *state)
}
like image 136
Vladimir Matveev Avatar answered Oct 28 '25 22:10

Vladimir Matveev