Rust中mockall::automock与Send+Sync+Any冲突问题求解
解决Mockall中Trait同时满足Send+Sync、Any转型与Mock的编译问题
问题重现
原代码实现了一个继承Send + Sync的Trait,包含返回&dyn Any的方法,普通结构体实现该Trait可正常编译,但添加#[automock]宏后编译失败:
use std::any::Any; use mockall::automock; #[automock] // 添加该宏后触发编译报错 pub trait MyTrait: Send + Sync { fn get_next(&self) -> &dyn Any; } pub struct MyStruct {} impl MyTrait for MyStruct { fn get_next(&self) -> &dyn Any { self } }
编译报错信息
25 | pub trait MyTrait: Send + Sync { | ^^^^^^^ `(dyn std::any::Any + 'static)` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `(dyn std::any::Any + 'static)`, which is required by `MockMyTrait: Sync` = note: required for `Unique<(dyn std::any::Any + 'static)>` to implement `Sync`
问题原因
dyn Any本身不自动实现Sync(或Send),而Mockall生成的MockMyTrait需要满足原Trait的Send + Sync约束。原Trait方法返回&dyn Any,意味着Mock的返回值仅被视为普通dyn Any,无法保证线程安全,因此编译器判定MockMyTrait不满足Sync约束。
解决方案
方案1:为返回的dyn Any添加Send + Sync约束(推荐)
修改Trait中方法的返回类型,明确要求返回的dyn Any同时满足Send + Sync,Mockall生成的代码会自动符合线程安全要求:
use std::any::Any; use mockall::automock; #[automock] pub trait MyTrait: Send + Sync { // 为dyn Any追加Send + Sync约束 fn get_next(&self) -> &(dyn Any + Send + Sync); } pub struct MyStruct {} impl MyTrait for MyStruct { fn get_next(&self) -> &(dyn Any + Send + Sync) { self // 空结构体自动实现Send + Sync,类型转型合法 } }
方案2:手动为Mock结构体实现Send + Sync(不推荐,需unsafe)
若无法修改原Trait定义,可通过unsafe代码手动为生成的MockMyTrait实现Send + Sync,但必须确保所有Mock返回的dyn Any实例都确实满足Send + Sync,否则会引入线程安全隐患:
// 在MockMyTrait生成后添加以下unsafe实现 unsafe impl Send for MockMyTrait {} unsafe impl Sync for MockMyTrait {}
内容的提问来源于stack exchange,提问作者Treagzhao
相关产品推荐
相关产品推荐

