Когда дело доходит до Box
и future
, почти всегда имеет смысл использовать Box::pin
вместо Box::new
:
use std::pin::Pin;
use futures::{future, Future};
fn test() -> Pin<Box<dyn Future<Output = Result<bool, ()>>>> {
Box::pin(future::ok(true))
}
async fn async_fn() -> bool {
test().await.unwrap()
}
Причина довольно интересная. Pin
имеет общую реализацию для Unpin
:
impl<P> Unpin for Pin<P> where
P: Unpin,
И Box<T>
внутри него безусловно Unpin
:
impl<T> Unpin for Box<T> where
T: ?Sized,
То есть Pin<Box<dyn Future>>
- это не закрепленное Future
. Все работает, но почему Box
само по себе нет? Это одно место, где Deref
мешает:
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
}
await
ожидает открепления Future
, а Box<dyn Future>
, созданный с помощью Box::new
, содержит Future
. Таким образом, он автоматически разыменовывается, и Unpin
теряется, если вы явно не заявите об этом с помощью Box<dyn Future + Unpin>
.
Редактировать: @ ÖmerErden прав в том, почему Box<dyn Future>
не будет работать.