Асинхронный хук в тисе, ожидаемая структура `Pin<Box<(dyn, найденная структура `Pin<Box<impl

Минимально воспроизводимый пример:

use std::pin::Pin;
use std::rc::Rc;
use yew::prelude::*;


// pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T>  + 'a>>;

pub struct UseSignTxHandle {
    api_call: Rc<dyn Fn() -> Pin<Box<dyn std::future::Future<Output = Option<String>>>>>,
}

impl UseSignTxHandle {
    pub fn api_call(&self) {
        (self.api_call)();
    }
}

impl Clone for UseSignTxHandle {
    fn clone(&self) -> Self {
        Self {
            api_call: self.api_call.clone(),
        }
    }
}

#[hook]
pub fn use_sign_tx_handle() -> UseSignTxHandle
{
    let state: UseStateHandle<Option<String>> = use_state(|| None);
    let phrase_option = state.clone();
    let api_call = {
        let phrase_option = phrase_option.clone();
        Rc::new(move || {
            let phrase_option = phrase_option.clone();
            let pin = Box::pin( async {
                if let Some(seed) = *phrase_option {
                    let events = "Hello World".to_string();
                    Some(events)
                } else {
                    None
                }
            });
            pin
            })
           
    };
    UseSignTxHandle { api_call }
}

Ошибка:

UseSignTxHandle { api_call }
   |                         ^^^^^^^^ expected trait object `dyn std::future::Future`, found opaque type
   |
  ::: /home/amiya/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:72:43
   |
72 |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
   |                                             ------------------------------- the found opaque type
   |
   = note: expected struct `Pin<Box<(dyn std::future::Future<Output = std::option::Option<std::string::String>> + 'static)>>`
              found struct `Pin<Box<impl std::future::Future<Output = std::option::Option<std::string::String>>>>`
   = note: required for the cast from `[closure@src/components/accounts/hooks/sign_tx_handle.rs:35:17: 35:24]` to the object type `dyn Fn() -> Pin<Box<(dyn std::future::Future<Output = std::option::Option<std::string::String>> + 'static)>>`

Попытка построить асинхронную функцию как хук в тисе:

use crate::components::accounts::account_store::PhraseStore;
use crate::components::accounts::functions::get_from_seed_sr;
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use subxt::{tx::PairSigner, PolkadotConfig};
use yew::prelude::*;
use yewdux::prelude::*;
use subxt::blocks::ExtrinsicEvents;
use subxt::config::WithExtrinsicParams;
use subxt::tx::BaseExtrinsicParams;
use subxt::tx::PlainTip;
use subxt::SubstrateConfig;

// pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T>  + 'a>>;

pub struct UseSignTxHandle {
    api_call: Rc<dyn Fn() -> Pin<Box<dyn std::future::Future<Output = std::option::Option<ExtrinsicEvents<WithExtrinsicParams<SubstrateConfig, BaseExtrinsicParams<SubstrateConfig, PlainTip>>>>>>>>,
}

impl UseSignTxHandle {
    pub fn api_call(&self) {
        (self.api_call)();
    }
}

impl Clone for UseSignTxHandle {
    fn clone(&self) -> Self {
        Self {
            api_call: self.api_call.clone(),
        }
    }
}

#[hook]
pub fn use_sign_tx_handle<T>(tx: T) -> UseSignTxHandle
where
    T: subxt::tx::TxPayload + 'static,
{
    let (store, _) = use_store::<PhraseStore>();
    let phrase_option = store.mnemonic_phrase.clone();
    let api_call = {
        let phrase_option = phrase_option.clone();
        Rc::new(move || {
            let phrase_option = phrase_option.clone();
            let pin = Box::pin(async {
                let client =
                    subxt::client::OnlineClient::<PolkadotConfig>::from_url("ws://127.0.0.1:9944")
                        .await
                        .unwrap();
                if let Some(seed) = phrase_option {
                    let pair = get_from_seed_sr(&seed);
                    let signer = PairSigner::new(pair);
                    let result = client
                        .tx()
                        .sign_and_submit_then_watch_default(&tx, &signer)
                        .await
                        .unwrap()
                        .wait_for_finalized()
                        .await
                        .unwrap();
                    let events = result.fetch_events().await.unwrap();
                    Some(events)
                } else {
                    None
                }
            });
            pin
        })
    };
    UseSignTxHandle { api_call }
}

Выдает ошибку:

 UseSignTxHandle { api_call }
   |                         ^^^^^^^^ expected trait object `dyn std::future::Future`, found opaque type

note: expected struct `Pin<Box<(dyn std::future::Future<Output = std::option::Option<ExtrinsicEvents<WithExtrinsicParams<SubstrateConfig, BaseExtrinsicParams<SubstrateConfig, PlainTip>>>>> + 'static)>>`
         found struct `Pin<Box<impl std::future::Future<Output = std::option::Option<ExtrinsicEvents<WithExtrinsicParams<SubstrateConfig, BaseExtrinsicParams<SubstrateConfig, PlainTip>>>>>>>`

Пожалуйста, предоставьте минимальный воспроизводимый пример, который является одновременно минимальным и воспроизводимым, ваш фрагмент не является ни тем, ни другим. Вероятно, замена pin на pin as _ исправит эту ошибку.

cafce25 07.02.2023 15:57
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как я и подозревал, as _ работает. Это необходимо для преобразования конкретного Pin<Box<impl Future<…>>> в трейт-объект Pin<Box<dyn Future<…>>>, ожидаемый UseSignTxHandle:

#[hook]
pub fn use_sign_tx_handle<T>(tx: T) -> UseSignTxHandle
where
    T: subxt::tx::TxPayload + 'static,
{
    let state: UseStateHandle<Option<String>> = use_state(|| None);
    let api_call = {
        Rc::new(move || {
            let state = state.clone();
            Box::pin(async move { state.as_ref().map(|_| "Hello World".to_string()) }) as _
        })
    };
    UseSignTxHandle { api_call }
}

Другие вопросы по теме