Is it possible to create a mutable value of a mutable reference in a pattern?

跟風遠走 提交于 2020-01-21 11:10:33

问题


When pattern-matching, you can specify that you'd like to get a mutable reference to the contained value by using ref mut:

let mut score = Some(42);
if let Some(ref mut s) = score {
    &mut s;
}

However, the inner value is not mutable:

error[E0596]: cannot borrow immutable local variable `s` as mutable
 --> src/main.rs:4:14
  |
4 |         &mut s;
  |              ^
  |              |
  |              cannot reborrow mutably
  |              try removing `&mut` here

I tried to add in another mut, but that was not valid:

if let Some(mut ref mut s) = score {
    &mut s;
}
error: the order of `mut` and `ref` is incorrect
 --> src/main.rs:3:17
  |
3 |     if let Some(mut ref mut s) = score {
  |                 ^^^^^^^ help: try switching the order: `ref mut`

error: expected identifier, found keyword `mut`
 --> src/main.rs:3:25
  |
3 |     if let Some(mut ref mut s) = score {
  |                         ^^^ expected identifier, found keyword

error: expected one of `)`, `,`, or `@`, found `s`
 --> src/main.rs:3:29
  |
3 |     if let Some(mut ref mut s) = score {
  |                             ^ expected one of `)`, `,`, or `@` here

回答1:


Not a direct answer, but possible workarounds

Create an intermediate variable

if let Some(ref mut s) = score {
    let mut s = s;
    &mut s;
}
#[derive(Debug)]
struct X;

enum Foo<T> {
    Bar(T),
    _Baz,
}

fn main() {
    let mut score = Foo::Bar(X);

    if let Foo::Bar(ref mut s) = score {
        //let x = s;
        //println!("{:?}", **x); ! not possible
        let x = &mut &mut *s; // &mut &mut X
        println!("{:?}", **x);
    }
}

For Option specifically

if let Some(ref mut s) = score.as_mut() {
    s; //:&mut &mut i32
}
if let Some(mut s) = score.as_mut() {
    &mut s;
}



回答2:


Below code may give an idea for the possible solution to the problem. It's just a sample & testable code to provide a tiny example that aimed at the issue. Of course it may not cover the whole intents and purposes.

fn main() {
    let mut score = Some(42i32);

    let res = if let Some(41) = score {
        println!("41 is matched");
        1i32
    } else if let Some(ref mut s) = score { //&mut score {
        //let mut s2 = s;
        //println!("s: {:#?}", s);
        test(&mut &mut *s); // This part may be like this for borrowing
        //println!("s: {:#?}", s);
        1i32
    } else {
        0i32
    };

    //println!("Result: {:#?}", score);
    assert_eq!(res, 1i32);
}

fn test(ref mut s: &mut &mut i32) -> i32 {
    //let mut s2 = s;
    return test2(&mut *s);
}

fn test2(n: &mut i32) -> i32 {
    *n += 1;
    //println!("Value: {}", *(*n));
    return *n;
}

Live Version: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c3e7e1ee712a31f74b201149365035f

Gist Link: https://gist.github.com/7c3e7e1ee712a31f74b201149365035f



来源:https://stackoverflow.com/questions/49710608/is-it-possible-to-create-a-mutable-value-of-a-mutable-reference-in-a-pattern

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!