如何将外部关联类型强制转换为我的本地结构类型?

How to coerce external associated types to my local struct types?

我有以下结构:

pub struct Liquidator<'a, P> {
    // ...
    pending_liquidations: HashMap<Address, PendingTransaction<'a, P>>,
    // ...
}

其中 PendingTransaction 是从 ethers-rs 导入的结构:

pub struct PendingTransaction<'a, P> {
    // ...
    provider: &'a Provider<P>,
    // ...
}

我正在实例化我的 Liquidator 结构并试图在 pending_transactions 中插入一个元素:

pub async fn do_something(&mut self, borrower: &Address) {
    // ...
    let pending_tx = contract_call.send().await?;
    self.pending_liquidations.entry(*borrower).or_insert(pending_tx);
}

(这里是send方法的definition)。

但代码无法编译:

error[E0308]: mismatched types
   --> liquidator/src/liquidator.rs:115:70
    |
24  | impl<'a, P> Liquidator<'a, P>
    |             - this type parameter
...
115 |                 self.pending_liquidations.entry(*borrower).or_insert(pending_tx);
    |                                                                      ^^^^^^^^^^ expected type parameter `P`, found associated type
    |
    = note: expected struct `ethers::prelude::PendingTransaction<'a, P>`
               found struct `ethers::prelude::PendingTransaction<'_, <M as ethers::prelude::Middleware>::Provider>

看起来类型不匹配。我如何“强制”send 返回的 PendingTransaction 对象的内部类型与本地 Liquidator 结构的类型相同?

更新:这是我的整个 liquidator.rs 文件。

您的复杂示例可以简化为:

struct Container<T>(T);

fn put_into_container<T, I>(container: &mut Container<T>, mut iterator: I)
    where I: Iterator
{
    container.0 = iterator.next().unwrap();
}

抛出:

error[E0308]: mismatched types
 --> src/lib.rs:6:19
  |
3 | fn put_into_container<T, I>(container: &mut Container<T>, mut iterator: I)
  |                       - this type parameter
...
6 |     container.0 = iterator.next().unwrap();
  |                   ^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
  |
  = note: expected type parameter `T`
            found associated type `<I as Iterator>::Item`

如果不告诉编译器 I::Item 的类型,它就无法知道它与 T 的类型相同。我们必须像这样明确地告诉它:

struct Container<T>(T);

fn put_into_container<T, I>(container: &mut Container<T>, mut iterator: I)
    where I: Iterator<Item = T> // now compiles!
{
    container.0 = iterator.next().unwrap();
}

同样,在您的示例中,您试图将 M::Provider 推入 P 而没有向编译器保证它们实际上是同一类型。你可以通过改变这个来做到这一点:

impl<'a, M, P> Liquidator<'a, M, P>
where
    M: Middleware + 'a,
    P: JsonRpcClient + 'a,
{
    // etc
}

进入这个:

impl<'a, M, P> Liquidator<'a, M, P>
where
    M: Middleware<Provider = P> + 'a,
    P: JsonRpcClient + 'a,
{
    // etc
}

应该允许代码编译。