Используйте макрос в реализации признака с асинхронными функциями

#rust #async-await #traits

Вопрос:

Вот минимальный пример использования async функции в черте:

 use async_trait::async_trait;

macro_rules! default_f {
    () => {
        async fn f() -> i32 { 0 }
    };
}

#[async_trait]
trait Tr {
    async fn f() -> i32;
}

struct S;

#[async_trait]
impl Tr for S {
    default_f!();  // error: `async` trait functions are not currently supported
    //async fn f() -> i32 { 42 }  // this compiles
}
 

Асинхронные функции в чертах пока не поддерживаются (rustc 1.53), но ящик async_trait обеспечивает обходной путь.

Несколько необычной вещью здесь является использование макроса для определения реализации функции по умолчанию f .

Я не совсем понимаю, почему я не могу использовать макрос здесь. Я предполагаю, что async_trait макрос и default_f макрос плохо сочетаются друг с другом.

С шаблоном правильный макрос выглядит следующим образом

 macro_rules! default_f {
    () => {
        fn f<'a>() -> Pin<Box<dyn core::future::Future<Output = i32>   Send   'a>>
        where Self: Sync   'a, 
        { 
            async fn f() -> i32 { 42 }
            Box::pin(f())
        }
    };
}
 

Есть ли способ сделать эту работу без необходимости использовать шаблон?

Детская площадка Ржавчины

Комментарии:

1. Я заметил, что похожая проблема сочетается async_trait с fehler::throws той же чертой характера. Я сделал обходной путь, что-то вроде этой игровой площадки . Не на 100% удовлетворительно, но для меня достаточно хорошо.