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

Rust中inquire库Filter闭包内HashSet借用冲突问题

解决Rust inquire库Filter闭包的借用冲突问题

错误原因分析

你遇到的e0502借用冲突,核心是Rust的借用规则限制:

  • 循环外定义的filter闭包捕获了selectedrotors的不可变借用,该借用的生命周期与filter变量一致,持续到函数结束。
  • 循环内的selectedrotors.insert(r)需要对同一变量进行可变借用,而Rust不允许同一时间存在可变借用与不可变借用,因此触发报错。

修复方案:使用RefCell实现内部可变性

通过RefCell的内部可变性特性,我们可以在持有不可变引用的同时修改内部数据,同时调整闭包的创建时机来适配借用规则。

修改后的完整代码:

use std::collections::HashSet;
use std::cell::RefCell;
use inquire::{Select, Filter};

// 假设Rotors是实现了必要 trait 的枚举
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
enum Rotors {
    RotorI,
    RotorII,
    RotorIII,
}

impl Rotors {
    fn iter() -> impl Iterator<Item = Self> {
        [Self::RotorI, Self::RotorII, Self::RotorIII].into_iter()
    }
}

pub fn getRotors() {
    let selectedrotors = RefCell::new(HashSet::<Rotors>::new());
    let options: Vec<Rotors> = Rotors::iter().collect();

    for _ in 0..3 {
        // 每次循环创建新的 filter,捕获 RefCell 的不可变引用
        let filter: Filter<Rotors> = &|_, cur_option, _, _| {
            !selectedrotors.borrow().contains(cur_option)
        };

        let r = Select::new("Select a rotor", options.to_vec())
            .with_filter(filter)
            .prompt()
            .unwrap();

        selectedrotors.borrow_mut().insert(r);
    }
}

关键改动说明

  • 用RefCell包裹HashSet:RefCell将编译期的借用检查延迟到运行时,允许我们通过borrow()获取不可变引用、borrow_mut()获取可变引用,避免编译期冲突。
  • 将filter移到循环内部:每次迭代创建新的闭包,其捕获的不可变借用仅在当前迭代内有效,不会阻碍后续的可变借用操作。
  • 闭包内使用borrow()检查存在性:确保仅允许未被选择的选项显示给用户,insert时用borrow_mut()修改内部集合。

内容的提问来源于stack exchange,提问作者Brandon Piña

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:21:42