Ни функции async
, ни impl Trait
не допускаются в чертах. Вы можете использовать связанные типы, чтобы стать ближе. Вот несколько идей:
pub trait ResourceTrait {
type FutType: Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::Next;
}
Реализация этого в настоящее время немного сложна, поскольку некоторые из необходимых инструментов либо еще не доступны, либо стабильны, либо содержат ошибки.
Может быть реализовано как:
impl ResourceTrait for Resource {
type FutType = FutureObj<'static, ()>;
fn prepare(&mut self, auth: &str) -> FutureObj<'static, ()> {
FutureObj::new(Box::new(
async move {
// Do async things
// You might get a lifetime issue here if trying to access auth,
// since it's borrowed.
}
))
}
}
Альтернативой для экзистенциальных типов может быть:
impl ResourceTrait for Resource {
// this is required since the real type of the async function
// is unnameable
existential type FutType = Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::FutType {
async move {
// Do async things. Might still encounter the same borrowing issues,
// since the lifetime of the returned Future isn't coupled to the
// lifetime of self.
// The workaround is to make copies of all required fields and move
// them into the Future
}
}
}
Это может работать, а может и не работать (так как функция находится в стадии разработки).
Для правильного заимствования таких параметров, как self
или auth
в возвращаемом будущем, нам также может потребоваться, чтобы вначале были доступны общие ассоциированные типы.
Чтобы обойти проблемы заимствования для self
, вы можете определить
struct Resource {
inner: Arc<ResourceInner>, // carries all actual state
}
, чтобы вы могли скопировать inner
в prepare
и переместить его в Future
.