请使用以下代码

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

例如,t可以是.iter_mut().find()闭包中的输入.

铁 rust 分析器和编译器将把类型&&str赋值n,将类型&u8赋值a

我的问题是为什么.一个级别的间接会走向何方?我本以为n会是&&mut &str型.

推荐答案

正如注释中所建议的那样,match ergonomics是模式匹配表达式"let (n, a) = t;"中起作用的内容.或者,更具体地说,正在应用"绑定模式规则".

编译器做了一些假设,并在一定程度上简化了匹配的引用.下面的代码(playground)使用了一些极端的方式来说明这种行为.下面的输出显示了引用的最终效果.

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);// <- t declared with type spec.
    let (n, a) = t;                               // <- destructuring assignment.
    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);
}

Output:

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),而第一个引用不是,所以在析构赋值时会丢失可变性.

Rust相关问答推荐

从Type::new()调用函数

`RwLockWriteGuard_,T`不实现T实现的特征

通过RabbitMQ取消铁 rust 中长时间运行的人造丝任务的策略

如何在嵌套的泛型 struct 中调用泛型方法?

如何在Rust中基于字符串 Select struct ?

如何迭代属性以判断相等性?

使用 select 处理 SIGINT 和子等待!无阻塞

提取指向特征函数的原始指针

根据掩码将 simd 通道设置为 0 的惯用方法?

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

仅在使用 &mut 或线程时borrow 的数据在闭包之外转义?

Rust 文件未编译到 dll 中

‘&T as *const T as *mut T’ 在 ‘static mut’ 项目中合适吗?

Rust Redis 中的 HSET 命令问题

无法理解 Rust 对临时值的不可变和可变引用是如何被删除的

将 Futures 的生命周期特征绑定到 fn 参数

意外的正则表达式模式匹配

如何为枚举中的单个或多个值返回迭代器

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?