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

在async函数中使用非Sync的HashMap遇编译错误

问题解决:避免DiffVoxelRepository的Sync要求

错误原因分析

你遇到的编译错误源于async_trait库的默认行为:它会强制生成的Future实现Send trait。对于get方法中的异步块来说,它捕获了&self引用,而&T要实现Send的前提是T必须实现Sync。但你的DiffVoxelRepository包含HashMap,标准库的HashMap并未实现Sync(其内部数据结构不支持多线程下的无锁共享访问),这导致DiffVoxelRepository不满足Sync,进而&DiffVoxelRepository不满足Send,最终异步块生成的Future也无法满足Send要求。

解决方案:使用async_trait的非Send变体

既然代码只在单线程环境运行,完全不需要Future具备Send能力。可以通过#[async_trait(?Send)]替代默认的#[async_trait],告诉库不要强制生成的Future实现Send。

修改后的代码

use std::{marker::PhantomData, collections::HashMap};
use async_trait::async_trait;

#[derive(PartialEq, Eq, Hash)]
struct IVec3 {
    pub x: i32,
    pub y: i32,
    pub z: i32
}

trait VoxelComponent : Copy + Send {}
enum VoxelRepositoryError{}

// 使用?Send标记,不强制Future为Send
#[async_trait(?Send)]
trait VoxelRepository<T: VoxelComponent> : Send {
    async fn get(&self, position: IVec3) -> Result<Option<T>, VoxelRepositoryError>;
    async fn set(&mut self, position: IVec3, component: Option<T>) -> Result<(), VoxelRepositoryError>;
}

struct DiffVoxelRepository<R: VoxelRepository<C>, C: VoxelComponent> {
    source_repository: R,
    cache: HashMap<IVec3, C>,
    _component: PhantomData<fn() -> C>
}

impl<R: VoxelRepository<C>, C: VoxelComponent> DiffVoxelRepository<R, C> {
    fn new(repository: R) -> DiffVoxelRepository<R, C> {
        DiffVoxelRepository {
            source_repository: repository,
            cache: HashMap::new(),
            _component: PhantomData
        }
    }
}

// 同样使用?Send标记
#[async_trait(?Send)]
impl<R: VoxelRepository<C>, C: VoxelComponent> VoxelRepository<C> for DiffVoxelRepository<R, C> {
    
    async fn get(&self, position: IVec3) -> Result<Option<C>, VoxelRepositoryError> {
        match self.cache.get(&position) {
            Some(value) =>  Ok(Some(*value)),
            None => self.source_repository.get(position).await
        }
    }

    async fn set(&mut self, position: IVec3, component: Option<C>) -> Result<(), VoxelRepositoryError>{
        match component {
            Some(c) => self.cache.insert(position, c),
            None => self.cache.remove(&position)
        };

        self.source_repository.set(position, component).await
    }
}

方案说明

#[async_trait(?Send)]会调整async_trait生成的代码,不再要求异步方法返回的Future实现Send。这样即使&DiffVoxelRepository不满足Send(因为结构体本身不是Sync),也不会触发编译错误——单线程运行时根本不需要跨线程传递Future。

这个方案既避免了使用Mutex带来的不必要开销,又完全符合你只在单线程运行的需求。

内容的提问来源于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.24 20:34:58