Open
Description
Minified example: (godbolt)
use std::task::{Poll, Waker};
pub enum State<T> {
Inactive,
Active(Waker),
Signalled(T),
}
#[unsafe(no_mangle)]
pub fn poll_state(st: &mut State<String>, w: &Waker) -> Poll<String> { // a
match st {
State::Signalled(_) => {
// Just checked the variant, take the value out.
let State::Signalled(v) = std::mem::replace(st, State::Inactive) else {
unreachable!() // This panic should be eliminated.
};
Poll::Ready(v)
}
_ => {
*st = State::Active(w.clone()); // b
Poll::Pending
}
}
}
The optimization is fragile. If we remove the state assignment on the second branch (b), or change function signature to operate on State<u8>
, then the unreachable panic in the first branch will be correctly eliminated.