Skip to content

Commit 678b2dd

Browse files
committed
Ensure unreachable branch is eliminated
1 parent 3ee8999 commit 678b2dd

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

futures-util/src/future/select.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,31 @@ where
9999
type Output = Either<(A::Output, B), (B::Output, A)>;
100100

101101
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
102+
/// # Safety
103+
///
104+
/// `value` must be a `Some` value.
105+
#[inline(always)]
106+
unsafe fn take_unchecked<T>(value: &mut Option<T>) -> T {
107+
// `Option::unwrap_unchecked` is introduced in 1.58.0, so we can’t use it here.
108+
match value.take() {
109+
// SAFETY: the safety contract must be upheld by the caller.
110+
None => core::hint::unreachable_unchecked(),
111+
Some(value) => value,
112+
}
113+
}
114+
102115
let (a, b) = self.inner.as_mut().expect("cannot poll Select twice");
103116

104117
if let Poll::Ready(val) = a.poll_unpin(cx) {
105-
return Poll::Ready(Either::Left((val, self.inner.take().unwrap().1)));
118+
// SAFETY: `a` refers to a future lives inside `self.inner`, which means `self.inner` must be a `Some`
119+
// value.
120+
return Poll::Ready(Either::Left((val, unsafe { take_unchecked(&mut self.inner) }.1)));
106121
}
107122

108123
if let Poll::Ready(val) = b.poll_unpin(cx) {
109-
return Poll::Ready(Either::Right((val, self.inner.take().unwrap().0)));
124+
// SAFETY: `b` refers to a future lives inside `self.inner`, which means `self.inner` must be a `Some`
125+
// value.
126+
return Poll::Ready(Either::Right((val, unsafe { take_unchecked(&mut self.inner) }.0)));
110127
}
111128

112129
Poll::Pending

0 commit comments

Comments
 (0)