在模式中创建可变引用的可变值是否可能?

7

在模式匹配时,您可以使用 ref mut 来指定要获取所包含值的可变引用:

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

然而,内部值是不可变的:
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

我尝试添加另一个mut,但是不合法:
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
你想要获得一个 &mut &mut T 吗? - Arjan
1
@Arjan 是正确的。请注意,我并不声称这是一个有用的事情,尽管我相信会有人来解释为什么在某些情况下它可能是有用的。 - Shepmaster
@edwardw 同意:我认为这算是一种变通方法,因为它要求被匹配的值具有 as_mut 方法,而不仅仅是一般的语法。 - Shepmaster
@Shepmaster 这个怎么样?解引用以访问 mut var 然后借用可变的两次:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a87aaed059097e8a72817f09560d782e - Ömer Erden
基本上是重新借用为可变的,然后将此 mut 引用作为可变引用借用。 - Ömer Erden
显示剩余4条评论
2个回答

2

虽然不是直接回答,但有可能的解决方法:

创建一个中间变量

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);
    }
}

针对 Option


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

if let Some(mut s) = score.as_mut() {
    &mut s;
}

-1
以下代码可能会给出解决问题的可能方案。这只是一个示例和可测试的代码,提供了一个针对该问题的微小示例。当然,它可能无法涵盖所有意图和目的。
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;
}

在线版本:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c3e7e1ee712a31f74b201149365035f

Gist链接:https://gist.github.com/7c3e7e1ee712a31f74b201149365035f


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接