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

HiD*_*der 4 enums rust

我有包含变量的枚举:

enum Asymmetric {
    One(i32),
    Two(i32, i32),
}
Run Code Online (Sandbox Code Playgroud)

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

// 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;
        }
        _ => {}
    }
}
Run Code Online (Sandbox Code Playgroud)

这会导致此错误:

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
Run Code Online (Sandbox Code Playgroud)

Luk*_*odt 13

感谢"匹配人体工程学"(在此处提出的 Rust 1.26中引入),您可以编写如下代码:

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

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

您也可以使用手动完成ref mut.看到这个工作代码(游乐场):

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

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

  • 通常你deref(with *)matched-on值而不是添加&&mut匹配匹配中的每个模式
  • _如果您不需要绑定到该名称,则应将其用作名称占位符

在您的情况下,您可以使用进一步简化代码if let.每当你只对一个match案例感兴趣时,你应该使用if let:

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