有没有一种干净的方法可以让Rust插件具有全局可变状态?

有没有一种干净的方法可以让Rust插件具有全局可变状态?,rust,Rust,我发现的唯一方法是使用不安全的单例函数: fn singleton() -> &'static mut HashSet<String> { static mut hash_map: *mut HashSet<String> = 0 as *mut HashSet<String>; let map: HashSet<String> = HashSet::new(); unsafe { if ha

我发现的唯一方法是使用不安全的单例函数:

fn singleton() -> &'static mut HashSet<String> {
    static mut hash_map: *mut HashSet<String> = 0 as *mut HashSet<String>;

    let map: HashSet<String> = HashSet::new();
    unsafe {
        if hash_map == 0 as *mut HashSet<String> {
            hash_map = mem::transmute(Box::new(map));
        }
        &mut *hash_map
    }
}
fn singleton()->&'static mut HashSet{
静态mut hash_映射:*mut HashSet=0作为*mut HashSet;
让map:HashSet=HashSet::new();
不安全{
如果hash_map==0作为*mut HashSet{
hash_map=mem::transmute(Box::new(map));
}
&mut*hash_映射
}
}
有更好的办法吗?也许我们可以在
插件注册器
功能中做些什么

全局可变状态是指可由多个过程宏和/或属性使用的可变变量

更新:

我正在编写一个编译器插件来提供
sql程序宏。我有一个
#[sql_table]
属性要在结构上使用,这样我就可以获得sql表的名称和列


我需要全局可变状态来保存属性中结构的名称和字段,以便过程宏可以检查所有标识符是否存在。

宏”有助于使全局初始值设定项不是静态的。如果hash_map==0 as*mut HashSet
,它会执行类似于您的
的操作,但如果多个线程同时尝试执行此操作,它会处理数据竞争

至于可变性,为了避免更多的数据竞争,您必须以某种方式保护它,可能需要使用
互斥锁

总而言之:

#[macro_use] extern crate lazy_static;
use std::sync::Mutex;
use std::collections::HashSet;

lazy_static! {
    static ref THINGS: Mutex<HashSet<String>> = Mutex::new(HashSet::new());
}

fn usage() {
    // unwrap only fails if the lock is poisoned:
    // if another thread panicked while holding the lock.
    THINGS.lock().unwrap().insert("thing".to_owned())
}
#[macro_use]外部板条箱惰性_静态;
使用std::sync::Mutex;
使用std::collections::HashSet;
懒惰的人!{
静态引用:Mutex=Mutex::new(HashSet::new());
}
fn用法(){
//仅当锁中毒时,展开才会失败:
//如果另一个线程在持有锁时惊慌失措。
THINGS.lock().unwrap().insert(“thing.to_owned())
}

你是说像语法扩展一样的插件吗?是的,我是说Rust编译器的插件。请注意,你的单例实例是为了并行访问而被破坏的。还有其他问题(,)可以帮助您正确创建一个。我相信(但不确定)编译器中很可能存在并行访问。