Вопрос или проблема
Я пытаюсь реализовать метод build_with_provider
для обобщенной структуры EthereumCheckpointStorageBuilder
. Как структура, так и метод используют один и тот же обобщенный ограничитель: M: Middleware + 'static
.
Я хочу объявить обобщенный параметр M
один раз и использовать его как в структуре, так и в методе. Однако я сталкиваюсь со следующей ошибкой:
метод `build_with_provider` не имеет параметров типа, но его объявление трейта имеет 1 параметр типа
Я попытался добавить отдельный обобщенный параметр P в метод build_with_provider, но это кажется избыточным и вызывает проблемы с From. Вот что я попробовал:
async fn build_with_provider<P>(
...
) -> Self::Output
где
P: Middleware + 'static,
M: From<P>,
Есть ли более чистый способ объявить обобщенный параметр без его повторения, и как я могу решить эту ошибку?
Определения структуры и трейта
Ниже приведен соответствующий код:
// Определение структуры
pub struct EthereumCheckpointStorageBuilder<M> {
_phantom: std::marker::PhantomData<M>,
}
// Реализация трейта
#[async_trait]
impl<M> BuildableWithProvider for EthereumCheckpointStorageBuilder<M>
где
M: Middleware + 'static,
{
type Output = EthereumCheckpointStorage<M>;
const NEEDS_SIGNER: bool = true;
async fn build_with_provider(
&self,
provider: M,
conn: &ConnectionConf,
locator: &ContractLocator,
) -> Self::Output {
EthereumCheckpointStorage::new(Arc::new(provider), conn, locator)
}
}
// Определение трейта
#[async_trait]
pub trait BuildableWithProvider {
async fn build_with_provider<M>(
&self,
provider: M,
conn: &ConnectionConf,
locator: &ContractLocator,
) -> Self::Output
где
M: Middleware + 'static;
}
Ответ или решение
Проблема с обобщениями в методе build_with_provider
для EthereumCheckpointStorageBuilder
При разработке системы, связанной с Ethereum, вы столкнулись с сложностями в реализации метода build_with_provider
для обобщенной структуры EthereumCheckpointStorageBuilder
. Давайте подробно разберем вашу проблему, выявим причины ошибок и предложим оптимальное решение.
Присутствующая Проблема
При попытке реализации метода у вас возникает ошибка:
method `build_with_provider` has 0 type parameters but its trait declaration has 1 type parameter
Это указывает на то, что компилятор Rust не может сопоставить параметры обобщения для метода, потому что вы пытаетесь объявить параметр M
в трейте, хотя он уже объявлен в структуре.
Обзор Кода
Ваша структура и реализация трейта выглядят следующим образом:
-
Определение структуры:
pub struct EthereumCheckpointStorageBuilder<M> { _phantom: std::marker::PhantomData<M>, }
-
Реализация трейта:
#[async_trait] impl<M> BuildableWithProvider for EthereumCheckpointStorageBuilder<M> where M: Middleware + 'static, { type Output = EthereumCheckpointStorage<M>; const NEEDS_SIGNER: bool = true; async fn build_with_provider( &self, provider: M, conn: &ConnectionConf, locator: &ContractLocator, ) -> Self::Output { EthereumCheckpointStorage::new(Arc::new(provider), conn, locator) } }
-
Определение трейта:
#[async_trait] pub trait BuildableWithProvider { async fn build_with_provider<M>( &self, provider: M, conn: &ConnectionConf, locator: &ContractLocator, ) -> Self::Output where M: Middleware + 'static; }
Решение Проблемы
Чтобы устранить данную ошибку и упростить реализацию, вам необходимо уменьшить количество дублирующихся параметров обобщения. Вместо того, чтобы вновь объявлять M
в методе трейта, можно использовать уже существующий параметр обобщения M
. Вот исправленный код:
-
Определение трейта с использованием обобщенного параметра
M
:#[async_trait] pub trait BuildableWithProvider<M>: Sized where M: Middleware + 'static, { async fn build_with_provider( &self, provider: M, conn: &ConnectionConf, locator: &ContractLocator, ) -> Self::Output; }
-
Реализация трейта остается неизменной:
#[async_trait] impl<M> BuildableWithProvider<M> for EthereumCheckpointStorageBuilder<M> where M: Middleware + 'static, { type Output = EthereumCheckpointStorage<M>; const NEEDS_SIGNER: bool = true; async fn build_with_provider( &self, provider: M, conn: &ConnectionConf, locator: &ContractLocator, ) -> Self::Output { EthereumCheckpointStorage::new(Arc::new(provider), conn, locator) } }
Заключение
В результате, теперь метод build_with_provider
будет использовать параметр обобщения M
, объявленный в трейте, который уже соответствует параметру в вашей структуре EthereumCheckpointStorageBuilder
. Это решение не только устраняет ошибку компиляции, но и делает ваш код более чистым и понятным.
Рекомендуется также регулярно проверять, чтобы ваши реализации трейтов и структуры использовали единообразные обобщенные параметры, что способствует легкости поддержки и расширяемости вашего кода.