Rust 元组解构与引用

问题描述 投票:0回答:1

获取以下代码

let t : &&mut (&str, u8) =  &&mut ("hallo", 1u8);
let (n, a) = t;
例如,

t
可以是
.iter_mut().find()
闭包中的输入。

Rust 分析器和编译器将分配

n
类型
&&str
a
类型
&u8

我的问题是为什么。一级间接指向哪里?我本来希望

n
具有类型
&&mut &str

rust pattern-matching
1个回答
0
投票

正如评论中所建议的,匹配人体工程学是在模式匹配表达式“

let (n, a) = t;
”中发挥作用的。

编译器做了一些假设,并在某种程度上简化了匹配的引用。下面的代码通过一些极端的方式来说明这种行为。下面的输出显示了对引用的最终影响。

fn typestr<T>(_: &T) -> &str { std::any::type_name::<T>() }

macro_rules! print_type {
    ( $($t: expr),* ) => {{ 
        $( print!("{}: {:<12}", stringify!($t), typestr(&$t)); )* println!();
    }}
}

fn main() {
    let t : &mut (&str, u8) =  &mut ("hallo", 1u8);
    let (n, a) = t;
    print_type!(n, a, t);
    
    let t : &&mut (&str, u8) =  &&mut ("hallo", 1u8);
    let (n, a) = t;
    print_type!(n, a, t);
    
    let t : &&&&mut (&str, u8) =  &&&&mut ("hallo", 1u8);
    let (n, a) = t;
    print_type!(n, a, t);
    
    let t : &mut &mut &mut &mut &mut (&str, u8) =  
            &mut &mut &mut &mut &mut ("hallo", 1u8);
    let (n, a) = t;
    print_type!(n, a, t);
}

输出

n: &mut &str   a: &mut u8     t: &mut (&str, u8)
n: &&str       a: &u8         t: &&mut (&str, u8)
n: &&str       a: &u8         t: &mut &&&mut (&str, u8)
n: &mut &str   a: &mut u8     t: &mut &mut &mut &mut &mut (&str, u8)

可以看出,第二个和第三个示例的解除引用已进行了一定程度的调整。输出的最后一行显示了如何为多个可变间接保留可变性。技巧是

&mut
需要应用于每个引用运算符。否则,可变性就会丢失。

上面链接的 RFC 中的此图显示了如何执行自动参考调整:

                        Start                                
                          |                                  
                          v                                  
                +-----------------------+                     
                | Default Binding Mode: |                     
                |        move           |                     
                +-----------------------+                     
               /                        \                     
Encountered   /                          \  Encountered       
  &mut val   /                            \     &val
            v                              v                  
+-----------------------+        +-----------------------+    
| Default Binding Mode: |        | Default Binding Mode: |    
|        ref mut        |        |        ref            |    
+-----------------------+        +-----------------------+    
                          ----->                              
                        Encountered                           
                            &val

因为在OP的示例中,只有第二个引用是可变的(

&&mut
),而第一个引用不是,所以在解构赋值时可变性丢失了。

© www.soinside.com 2019 - 2024. All rights reserved.