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

如何重构Rust代码,将借用检查错误延迟至运行时而非编译时?

解决方案:通过运行时借用检查实现会话的全局存储

核心思路

由于你仅能修改State,无法改动Engine和Session,要突破编译期借用检查的限制,可通过Rc<RefCell<Engine>>包装Engine实现共享所有权与运行时可变借用,再配合Option<Session<'static>>存储会话——这里的'static生命周期通过可控的unsafe转换实现,实际由Rc保证Engine存活时间长于会话,同时通过运行时检查确保同一时间仅存在一个会话。

具体实现

不可修改的原结构体(保留)

struct Engine;

impl Engine {
    fn new_session(&mut self) -> Session {
        Session {
            engine: self,
            items: Vec::new(),
        }
    }

    fn end(&mut self, items: Vec<String>) {
        println!("Submitted items: {}", items.join(", "));
    }
}

struct Session<'a> {
    engine: &'a mut Engine,
    items: Vec<String>,
}

impl<'a> Session<'a> {
    fn add(&mut self, item: &str) {
        self.items.push(item.to_string());
    }
}

impl<'a> Drop for Session<'a> {
    fn drop(&mut self) {
        let items = std::mem::take(&mut self.items);
        self.engine.end(items);
    }
}

修改后的State结构体

use std::cell::RefCell;
use std::rc::Rc;

struct State {
    engine: Rc<RefCell<Engine>>,
    current_session: Option<Session<'static>>,
}

impl State {
    fn new() -> Self {
        State {
            engine: Rc::new(RefCell::new(Engine)),
            current_session: None,
        }
    }

    // 创建会话:运行时检查是否已有活跃会话
    fn start_session(&mut self) -> Result<(), &'static str> {
        if self.current_session.is_some() {
            return Err("已有活跃会话,无法创建新会话");
        }

        // 临时获取Engine可变引用,通过unsafe转换生命周期为'static
        // Rc保证Engine存活时间长于会话,运行时检查确保引用安全
        let mut engine_ref = self.engine.borrow_mut();
        let session = unsafe {
            std::mem::transmute::<Session<'_>, Session<'static>>(engine_ref.new_session())
        };
        self.current_session = Some(session);
        Ok(())
    }

    // 获取当前会话的可变引用
    fn get_session(&mut self) -> Option<&mut Session<'static>> {
        self.current_session.as_mut()
    }

    // 手动销毁会话
    fn end_session(&mut self) {
        self.current_session.take();
    }
}

使用示例

fn main() {
    let mut state = State::new();

    state.start_session().unwrap();
    if let Some(session) = state.get_session() {
        session.add("apple");
        session.add("banana");
    }
    state.end_session();

    state.start_session().unwrap();
    if let Some(session) = state.get_session() {
        session.add("coconut");
        session.add("durian");
    }
    state.end_session();
}

输出结果

Submitted items: apple, banana
Submitted items: coconut, durian

安全说明

  • 此处的unsafe操作是可控的:Rc确保Engine的生命周期覆盖所有会话,RefCell和Option的运行时检查保证同一时间仅存在一个Engine的可变引用,不会出现悬垂引用或数据竞争。
  • 会话的创建与销毁完全由State的方法手动控制,符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 03:16:12