Rust跨线程异步回调报std::marker::Copy未实现错误如何修复
问题根因
你遇到的报错源于两处不必要的错误约束:
- 所有接收
callback参数的方法(get_replyer/AsynkReplyer::new/start_subscription_handler/handle_request)都给回调加了多余的Copytrait约束,你的闭包捕获了Publisher实例,而Publisher包含String等不可Copy的字段,自然无法满足约束。 Publisher结构体的PhantomData用了*const T类型,原生指针*const T默认不实现Send/Synctrait,导致整个Publisher无法跨线程安全传递,触发第二个和第三个报错。
修复方案
1. 移除所有回调的Copy约束
把四个方法中callback参数的+ Copy约束全部删掉即可,你的场景完全不需要Copy能力,只要保证回调可克隆/移动就足够:
// 示例:修改get_replyer签名,其他三个方法同理修改 pub async fn get_replyer<Req, Resp, Fut>( &self, subject: String, callback: impl Fn(Arc<Mutex<Req>>) -> Fut + Send + Sync + 'static, // 删掉末尾的Copy ) -> AsynkReplyer<Req, Resp>
2. 修正Publisher的PhantomData定义
把PhantomData<*const T>换成不带指针的类型,即可自动继承T的Send/Sync实现:
#[derive(Clone)] pub struct Publisher<T> { connection: Connection, subject: String, // 替换为普通PhantomData<T>,如果要标记不持有T的所有权,也可以用PhantomData<fn() -> T> resource_type: PhantomData<T>, }
3. 修复main函数中闭包的小问题
你调用async方法publish时没有加await,同时不需要额外克隆p,修改后代码如下:
let _submission_replyer: AsynkReplyer<Request, Response> = node .get_replyer("request".into(), move |req: Arc<Mutex<Request>>| async move { // 提前把Request克隆出来,避免拿着MutexGuard跨await let req = req.lock().unwrap().clone(); p.publish(req).await.expect("publish failed"); Ok(Response {}) }) .await;
改完以上三处后所有报错都会消失,不需要给Publisher或者Request加Copy trait,也没有大的架构设计缺陷。
内容的提问来源于stack exchange,提问作者Seg
相关产品推荐
相关产品推荐

