You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在Rust的match模式中添加&会引发移动错误?

Rust中匹配&Cons(x,y)引发移动错误的原因解析

原可编译代码

#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

use std::ops::Deref;
use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let value = Rc::new(RefCell::new(5));

    let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));

    let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
    let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));
    
    match &b {
        Cons(x,y)=>{// 原匹配分支
            match y.deref(){
                Cons(t,l)=>{
                    *t.borrow_mut() +=10;
                }
                _=>{}
            }
        }
        _=>{}
    }

    println!("a after = {:?}", a);
    println!("b after = {:?}", b);
    println!("c after = {:?}", c);
}

修改后的错误代码片段

将上述代码中的匹配分支修改为:

match &b {
    &Cons(x,y)=>{// 添加了引用符号
        match y.deref(){
            // 后续逻辑不变
        }
    }
    _=>{}
}

修改后触发编译错误:

error[E0507]: cannot move out of a shared reference

原因解释

核心问题出在模式匹配的解构逻辑和引用的交互方式上:

  • 原代码里match &b匹配的是b的引用,分支Cons(x,y)属于隐式引用解构——Rust会自动把&Cons(...)解构为Cons(x,y),这里的x和y都是对应字段的引用(准确说是&Rc<RefCell<i32>>和&Rc<List>),完全不需要移动原数据。

  • 修改后的&Cons(x,y)模式,相当于告诉Rust:要匹配一个被引用包裹的Cons枚举,然后把里面的x和y直接取出来。但b本身是Cons(Rc<...>, Rc<...>)类型,&b是&Cons(...),当用&Cons(x,y)去匹配时,Rust会尝试把Cons(x,y)从引用里"拆出来",也就是要将b的两个字段(Rc<RefCell<i32>>和Rc<List>)移动到x和y中。

而Rc并没有实现Copy trait,只能通过clone()复制引用计数。尝试从&b这个共享引用里移动出Rc实例,直接违反了Rust的借用规则——共享引用不允许修改或移动底层数据,因此触发了cannot move out of a shared reference错误。

简单来说:你以为加&是保留引用,实际上这个&是模式的一部分,要求Rust把引用里的整个Cons结构解构出来并移动字段,反而触发了移动操作。

内容的提问来源于stack exchange,提问作者violet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:30:16