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

Rust测试场景下创建模拟`sink`遇到的所有权与生命周期问题

错误原因

两个编译错误均源于所有权与借用规则冲突:

  1. get_sink 闭包内创建的 sink 是栈上局部变量,将其引用存入外层 sinks 后,sink 会被移动到返回的闭包中,局部变量的引用会直接变为悬垂引用,不符合Rust生命周期约束。
  2. 代码先对 sink 做不可变借用存入 sinks,随后又将 sink 所有权移动到返回的闭包中,同一时间存在不可变借用和可变使用,违反借用规则。
方案说明

你提到的用共享智能指针的思路完全正确,需要配合内部可变性容器实现需求:

  • 串行场景下使用 Rc<RefCell<Vec<i32>>> 即可,无需拆分两种类型,所有持有者都可通过 borrow_mut() 修改内部值,borrow() 读取内部值。
  • 若后续要适配rayon并行场景,将 Rc<RefCell> 替换为线程安全的 Arc<Mutex<Vec<i32>>> 即可,不需要修改 func_under_test 的核心逻辑。
串行场景可运行代码
use std::rc::Rc;
use std::cell::RefCell;

fn func_under_test<GetSink, F>(
    mut get_sink: GetSink
)
where
    GetSink: FnMut(usize) -> F,
    F: FnMut(i32) -> (),
{
    let idxs : Vec<usize> = (0..2).collect();
    idxs.iter().for_each(|&i| {
        let mut sink = get_sink(i);
        sink(0i32);
        sink(1i32);
        sink(2i32);
    });
}

fn main() {
    let mut sinks : Vec<Rc<RefCell<Vec<i32>>>> = vec![];
    let get_sink = |i: usize| {
        let sink = Rc::new(RefCell::new(Vec::new()));
        sinks.push(sink.clone());
        move |x : i32| {
            sink.borrow_mut().push(x);
        }
    };

    func_under_test(get_sink);

    assert_eq!(*sinks[0].borrow(), vec![0i32, 1i32, 2i32]);
    assert_eq!(*sinks[1].borrow(), vec![0i32, 1i32, 2i32]);
}
并行场景适配代码

替换智能指针类型即可兼容rayon并行逻辑:

use std::sync::{Arc, Mutex};

fn func_under_test<GetSink, F>(
    mut get_sink: GetSink
)
where
    GetSink: FnMut(usize) -> F + Send,
    F: FnMut(i32) -> () + Send,
{
    // 此处直接换成rayon的par_iter即可正常并行运行
    let idxs : Vec<usize> = (0..2).collect();
    idxs.iter().for_each(|&i| {
        let mut sink = get_sink(i);
        sink(0i32);
        sink(1i32);
        sink(2i32);
    });
}

fn main() {
    let mut sinks : Vec<Arc<Mutex<Vec<i32>>>> = vec![];
    let get_sink = |i: usize| {
        let sink = Arc::new(Mutex::new(Vec::new()));
        sinks.push(sink.clone());
        move |x : i32| {
            sink.lock().unwrap().push(x);
        }
    };

    func_under_test(get_sink);

    assert_eq!(*sinks[0].lock().unwrap(), vec![0i32, 1i32, 2i32]);
}

该实现完全兼容你的使用场景:测试环境下用向量存储结果做断言,生产环境只需修改get_sink的实现返回写文件的闭包,无需调整func_under_test的核心逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:36:02