Can a future used only by `async fn` assume it won't be polled again after becoming ready?
@jacobsa Aar
·
2026-04-24
·
via The Rust Programming Language Forum - Latest posts
Hi all, I thought about this more and I don't think the consensus above necessairly makes sense. You all seem to think the status quo is appropriate because it allows the compiler to optimize away the last state machine transition (from state that returns to "I have returned" state). But it certainly can't do that in general, as it may introduce UB depending on what that state does. Here is a super simple example: // # Safety // // The caller must guarantee the Option is Some. async unsafe fn take_some<T>(o: &mut Option<T>) -> T { unsafe { o.take().unwrap_unchecked() } } This can be called to obtain a Future , which is explicitly documented as allowing polling again after completion. As far as I can tell that means the compiler is forced to insert a transition to a state that will panic if polled again or else it will cause UB in safe code like this function: fn inefficient_take_that_might_panic<T>(o: &mut Option<T>) -> Option<T> { if o.is_none() { return None; } // Safety: we confirmed this is Some. let mut future = pin!(unsafe { take_some(o) }); let result = match future .as_mut() .poll(&mut Context::from_waker(Waker::noop())) { Poll::Ready(result) => result, _ => std::unreachable!(), }; // Totally valid by the Future docs. let _ = future.poll(&mut Context::from_waker(Waker::noop())); Some(result) } I'm pretty sure you can come up with similar examples that don't involve the unsafe keyword as well.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。