Rust中Arc包裹的dyn Provider trait无法克隆的问题求助
我来帮你捋清楚这个问题的核心,其实你遇到的不是Arc<dyn Provider>不能克隆——Arc<dyn Provider>本身是完全可以克隆的,因为Arc的克隆操作只是复制指针,和内部的动态类型无关。真正的问题出在UNI_V3_POOL::new的参数类型约束上:
从错误信息来看,UNI_V3_POOL::new的第二个参数大概率要求是一个**编译期大小已知(Sized)**的类型,而你传入的self.provider.clone()返回的Arc<dyn Provider>,虽然Arc本身是固定大小的胖指针,但如果UNI_V3_POOL::new的参数定义是T: Provider而不是Arc<dyn Provider>,编译器会尝试把Arc<dyn Provider>当作T来匹配,这时候就会触发dyn Provider是动态大小类型(DST)的错误。
给你几个可行的解决思路:
调整
UNI_V3_POOL::new的参数类型
如果UNI_V3_POOL是你自己实现的结构体,直接把new方法的第二个参数改成Arc<dyn Provider>:impl UNI_V3_POOL { pub fn new(pool_address: Address, provider: Arc<dyn Provider>) -> Self { // 原有的初始化逻辑 } }这样传
self.provider.clone()就完全没问题了,因为Arc<dyn Provider>是固定大小的胖指针,满足Sized约束。把
UniswapBroker改成泛型结构体
如果你没办法修改UNI_V3_POOL的代码,那可以把UniswapBroker定义成泛型类型,让provider的类型是具体的Provider实现,而不是动态的dyn trait:pub struct UniswapBroker<P> where P: Provider + 'static, { provider: Arc<P>, pool_address: Address, quoter_address: Address, token0: Address, token1: Address, fee: u32, config: serde_json::Value, swap_callback: SwapCallback, } // 初始化方法也要对应改成泛型 impl<P: Provider + 'static> UniswapBroker<P> { pub fn new(provider: P, pool_address: Address, /* 其他参数 */) -> Self { Self { provider: Arc::new(provider), pool_address, // 其他字段赋值 } } }这样
self.provider.clone()得到的是Arc<P>,而P是编译期已知大小的具体类型,完全符合UNI_V3_POOL::new的参数约束。检查
Providertrait的对象安全性
最后再确认下alloy::providers::Provider这个trait是不是对象安全的——如果它的定义里有带Sized约束的方法,那dyn Provider本身就是不合法的,这时候你只能用泛型的方式来处理,没办法用dyn trait。
另外你之前尝试去掉dyn的思路是对的,但因为Provider是trait,直接用Arc<Provider>会编译报错,必须要么用泛型Arc<P: Provider>,要么用Arc<dyn Provider>,这也是Rust里处理trait对象的基本规则。
内容来源于stack exchange

