Hola a todos,
Estoy experimentando con la programación asíncrona en Rust utilizando el modificador async
y la palabra clave await
. Sin embargo, estoy teniendo algunos problemas al tratar de compilar mi código. Aquí está el código que estoy utilizando:
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
async fn my_async_function() -> i32 {
// Alguna lógica asíncrona aquí
return 42;
}
struct MyFuture {
value: Option<i32>,
}
impl Future for MyFuture {
type Output = i32;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if let Some(value) = self.value.take() {
Poll::Ready(value)
} else {
self.value = Some(cx.waker().wake_by_ref().clone());
Poll::Pending
}
}
}
async fn my_async_function_that_uses_future() {
let future = MyFuture { value: Some(42) };
let result = await!(future);
println!("Resultado: {}", result);
}
#[tokio::main]
async fn main() {
await!(my_async_function_that_uses_future()).await;
}
Cuando intento compilar este código, obtengo el siguiente error:
error[E0658]: async block may outlive the current function, but it borrows `*self` which is owned by the current function
--> src/main.rs:20:13
|
18 | impl Future for MyFuture {
| --------------- `self` is borrowed here
19 | type Output = i32;
20 | fn poll<'a>(self: Pin<&'a mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
| ^^^^ --- `self` is borrowed here
| |
| borrowed value does not live long enough
...
23 | self.value = Some(cx.waker().wake_by_ref().clone());
| ------- `self` is borrowed here
...
26 | }
| - returned value dropped here while still borrowed
...
35 | }
| - borrowed value needs to live until here
...
42 | }
| - `self` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.
error: could not compile `async_await_example`
¿Qué puede estar causando este error y cómo puedo solucionarlo?
¡Gracias de antemano!
¡Hola Brisa!
Tengo algunas observaciones sobre tu código que creo que podrían ayudarte a solucionar los problemas:
Primero, parece que estás intentando utilizar una antigua sintaxis de await
(es decir, await!(future)
). En las versiones más recientes de Rust, solo necesitas usar .await
para esperar una Future
. Así que deberías cambiar await!(future)
por future.await
.
En la función poll
estás haciendo un wake_by_ref()
y luego asignando algo a self.value
. Esto no es correcto y es la causa del error E0658. En cambio, si quieres crear una Future
sencilla que retorne Poll::Ready
cuando haya un valor, no necesitas interactuar con el Context
ni con el Waker
.
En Rust, la función main
no necesita ser una función async
para usar .await
, puedes utilizar la macro #[tokio::main]
directamente y dentro de la función main, simplemente llamas a las funciones asíncronas y aplicas el .await
.
Con esas correcciones, el código debería verse algo así:
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
async fn my_async_function() -> i32 {
// Alguna lógica asíncrona aquí
42 // En Rust, no es necesario usar `return` para el valor final de una función.
}
struct MyFuture {
value: Option<i32>,
}
impl Future for MyFuture {
type Output = i32;
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
// No necesitas interactuar con el contexto ni el waker aquí.
if let Some(value) = self.value.take() {
Poll::Ready(value)
} else {
// En una implementación real, aquí manejarías el caso donde aún no hay un valor disponible.
// Pero, por simplicidad, vamos a asumir que siempre hay un valor y siempre está listo.
Poll::Pending
}
}
}
async fn my_async_function_that_uses_future() -> i32 { // Hacemos que retorne i32
let mut future = MyFuture { value: Some(42) };
let result = future.await;
println!("Resultado: {}", result);
result // Retornamos el resultado
}
#[tokio::main]
async fn main() {
let _result = my_async_function_that_uses_future().await;
}
Las correcciones son:
.await
en lugar de await!()
, que es obsoleto.poll
para quitar la lógica incorrecta del waker.main
para usar .await
directamente sin necesidad de hacerlo sobre await!()
.Prueba con esos cambios y deberías poder compilar y ejecutar tu código. ¡Espero que esto te ayude! Si tienes más dudas, ¡aquí estoy!