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

Rust中如何将&[&mut Self]转换为&[(&mut Self, MappedMemoryRange)]

解决Rust中MappedMemory trait默认实现的引用所有权错误

问题背景

定义了如下MappedMemory trait和MappedMemoryRange结构体:

pub trait MappedMemory {
    fn range(&self) -> MappedMemoryRange;
    
    fn flush(&mut self);
    fn flush_range(&mut self, range: MappedMemoryRange);
    fn flush_ranges(&mut self, ranges: &[MappedMemoryRange]);
    
    fn flush_multiple(memories: &[&mut Self]);
    fn flush_multiple_ranges(memories: &[(&mut Self, MappedMemoryRange)]);
}

pub struct MappedMemoryRange {
    pub offset: u64,
    pub size: usize
}

尝试为flush_multiple编写默认实现,将&[&mut Self]转换为&[(&mut Self, MappedMemoryRange)]后调用flush_multiple_ranges,代码如下:

let memories_and_ranges: Vec<(&mut Self, MappedMemoryRange)> = memories
    .into_iter()
    .map(|m| (*m, m.range()))
    .collect();

触发以下错误:

error[E0507]: cannot move out of `*m` which is behind a shared reference
  --> crates\xyz\src\objects\memory.rs:44:23
   |
44 |             .map(|m| (*m, m.range()))
   |                       ^^ move occurs because `*m` has type `&mut Self`, which does not implement the `Copy` trait

错误原因

memories的类型是&[&mut Self],调用into_iter()后得到的迭代器元素是&&mut Self(对可变引用的共享引用)。尝试*m会试图将内部的&mut Self从共享引用中移出,但&mut Self并未实现Copy trait,Rust不允许这种移动操作——因为共享引用背后的数据不能被随意移动,否则会破坏借用规则。

解决方案

不需要移动&mut Self,而是通过重新借用的方式获取合法的&mut Self引用,有两种清晰的实现方式:

方式1:使用AsMut::as_mut()方法

AsMut trait为&&mut T提供了默认实现,调用as_mut()可以安全地获取内部的&mut T引用:

fn flush_multiple(memories: &[&mut Self]) {
    let memories_and_ranges: Vec<(&mut Self, MappedMemoryRange)> = memories
        .iter()
        .map(|m| (m.as_mut(), m.range()))
        .collect();
    Self::flush_multiple_ranges(&memories_and_ranges);
}

方式2:显式双重解引用后重新借用

通过&mut **m显式完成双重解引用(先得到Self,再创建可变引用),效果和as_mut()一致:

fn flush_multiple(memories: &[&mut Self]) {
    let memories_and_ranges: Vec<(&mut Self, MappedMemoryRange)> = memories
        .iter()
        .map(|m| (&mut **m, m.range()))
        .collect();
    Self::flush_multiple_ranges(&memories_and_ranges);
}

两种方式都遵循了Rust的借用规则:没有移动原有引用,只是创建了临时的可变借用,供flush_multiple_ranges使用。


内容的提问来源于stack exchange,提问作者Rick de Water

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:07:31