无法更改枚举的一个值,因为它是重新赋值的不可变变量

时间:2016-10-07 13:34:28

标签: enums rust

我的枚举包含变量:

enum Asymmetric {
    One(i32),
    Two(i32, i32),
}

我想只更改已存在的枚举的一个字段,而不重新分配整个枚举。我的代码(playground):

// Does not compile
fn main() {
    let two = Asymmetric::Two(4, 5);
    let mut vec = vec![two];
    foo(&mut vec[0]);
}

fn foo(baa: &mut Asymmetric) {
    match baa {
        &mut Asymmetric::Two(x0, x1) => {
            x0 = 6;
        }
        _ => {}
    }
}

这会导致此错误:

error[E0384]: re-assignment of immutable variable `x0`
  --> src/main.rs:16:13
   |
15 |         &mut Asymmetric::Two(x0, x1) => {
   |                              -- first assignment to `x0`
16 |             x0 = 6;
   |             ^^^^^^ re-assignment of immutable variable

1 个答案:

答案 0 :(得分:13)

感谢"匹配人体工程学" (在Rust 1.26中引入,proposed here),您可以像这样编写代码:

fn foo(baa: &mut Asymmetric) {
    match baa {
        Asymmetric::Two(x0, _) => {
            *x0 = 6;
        }
        _ => {}
    }
}

由于baa是一个可变引用,但您与[Asymmetric::Two(x0, _))匹配的模式不是,因此名称x0会自动绑定为可变引用。

您也可以使用ref mut手动执行此操作。请参阅此工作代码(playground):

fn foo(baa: &mut Asymmetric) {
    match *baa {
        Asymmetric::Two(ref mut x0, _) => {
            *x0 = 6;
        }
        _ => {}
    }
}

与您的错误无关但会提高代码质量的一些细微更改:

  • 通常您会*编辑match ed-on值,而不是将&&mut添加到匹配中的每个模式
  • 如果您不需要绑定到该名称,则应使用_作为名称占位符

在您的情况下,您可以使用if let进一步简化代码。如果您只对match个案例感兴趣,则应使用if let代替:

fn foo(baa: &mut Asymmetric) {
    if let Asymmetric::Two(x0, _) = baa {
        *x0 = 6;
    }
}