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

Rust报错cannot assign to value behind & reference问题解析

Rust 编译错误 E0594 问题解答

核心报错为:cannot assign to first.value, which is behind a & reference,以下针对三个疑问逐一说明:

疑问1:为什么let mut first =写法无法让编译器认可first的可变性,支持修改first.value

Rust的可变性规则分为两层,二者互不干扰:

  • 第一层是变量绑定本身的可变性:由let mut声明,代表这个变量存储的值可以被替换,比如你可以让一个引用类型的变量重新指向其他地址。
  • 第二层是引用指向内容的访问权限:由引用类型决定,&T是不可变共享引用,仅提供读权限;&mut T是可变独占引用,提供读写权限。

你写的let mut first = &all_my_data[0]中,let mut仅让first这个变量本身可以被重新赋值(比如写first = &all_my_data[1]是合法的),但first持有的是不可变引用&Data,无论变量本身是否可变,都不能通过不可变引用修改指向的内容,因此修改first.value会触发报错。只有将右侧改为&mut all_my_data[0]拿到可变引用,才具备修改内部字段的权限。

疑问2:这个异常表现是否是因为数据被包裹在Box中导致的特殊行为?

不是。
Box<T>是堆分配的智能指针,实现了标准的Deref/DerefMut trait,会透明转发内部值的借用权限,行为和直接存储T完全一致,不会改变Rust的借用规则。你可以将代码中的Box移除,直接向Vec中 push Data实例,依然会触发完全相同的E0594错误。

疑问3:赋值语句右侧的mut和左侧的mut作用有什么差异?

两个位置的mut修饰目标完全不同,作用无关联:

  • 等号左侧let mut 变量名中的mut:修饰变量绑定本身,代表该变量可以被重新赋值,不改变变量持有值的访问权限。
  • 等号右侧&mut T中的mut:修饰引用的访问权限,代表这是可变独占引用,只有持有该类引用时,才能修改引用指向的内存数据。

可以通过以下代码快速理解二者差异:

let mut data = Data::new("test");
let mut other_data = Data::new("other");

// 变量本身不可变,但持有可变引用:可以改指向的内容,不能让变量重新指向
let a = &mut data;
a.value = "new value".to_string(); // 合法
// a = &mut other_data; // 报错:a是不可变绑定,不能重新赋值

// 变量本身可变,但持有不可变引用:可以让变量重新指向,不能改指向的内容
let mut b = &data;
b = &other_data; // 合法
// b.value = "new value".to_string(); // 报错:b持有的是不可变引用,无写权限

// 变量可变+持有可变引用:既可以重新指向,也可以修改指向的内容
let mut c = &mut data;
c.value = "new value".to_string(); // 合法
c = &mut other_data; // 合法

可复现代码

#![allow(unused)]
fn main() {
    let mut all_my_data = Vec::new();
    
    all_my_data.push(Box::new(
        Data::new("Hello World!"),
        ),
    );
    all_my_data.push(Box::new(
        Data::new("This is the end of the World!"),
        ),
    );
    all_my_data.push(Box::new(
        Data::new("Goodbye!"),
        ),
    );
    
    let mut first = &all_my_data[0]; // This errors out
    //let mut first = &mut all_my_data[0]; // This works
    first.value = String::from("Hello New World!");
    println!("First: {:?}", first);
    let second = &all_my_data[1];
    println!("Second: {:?}", second);
    let third = &all_my_data[2];
    println!("Third: {:?}", third);
}

#[derive(Debug)]
struct Data {
    value: String,
}

impl Data {
    pub fn new(value: &str) -> Data {
        Data {
            value: value.to_string()
        }
    }
}

编译报错信息

error[E0594]: cannot assign to `first.value`, which is behind a `&` reference
  --> src/main.rs:20:5
   |
18 |     let mut first = &all_my_data[0]; // This errors out
   |                     --------------- help: consider changing this to be a mutable reference: `&mut all_my_data[0]`
19 |     //let mut first = &mut all_my_data[0];
20 |     first.value = String::from("Hello New World!");
   |     ^^^^^^^^^^^ `first` is a `&` reference, so the data it refers to cannot be written

For more information about this error, try `rustc --explain E0594`.
error: could not compile `playground` due to previous error

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:01:29