Skip to content

Commit

Permalink
FillBuf: Do not call poll_fill_buf twice
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Dec 24, 2023
1 parent e6735f3 commit c179201
Showing 1 changed file with 7 additions and 13 deletions.
20 changes: 7 additions & 13 deletions futures-util/src/io/fill_buf.rs
Expand Up @@ -3,6 +3,7 @@ use futures_core::task::{Context, Poll};
use futures_io::AsyncBufRead;
use std::io;
use std::pin::Pin;
use std::slice;

/// Future for the [`fill_buf`](super::AsyncBufReadExt::fill_buf) method.
#[derive(Debug)]
Expand Down Expand Up @@ -30,19 +31,12 @@ where
let reader = this.reader.take().expect("Polled FillBuf after completion");

match Pin::new(&mut *reader).poll_fill_buf(cx) {
// We don't need to poll a second time for EOF, and doing so is likely to return Poll::Pending
Poll::Ready(Ok(&[])) => Poll::Ready(Ok(&[])),
// With polonius it is possible to remove this inner match and just have the correct
// lifetime of the reference inferred based on which branch is taken
Poll::Ready(Ok(_)) => match Pin::new(reader).poll_fill_buf(cx) {
Poll::Ready(Ok(slice)) => Poll::Ready(Ok(slice)),
Poll::Ready(Err(err)) => {
unreachable!("reader indicated readiness but then returned an error: {:?}", err)
}
Poll::Pending => {
unreachable!("reader indicated readiness but then returned pending")
}
},
Poll::Ready(Ok(slice)) => {
// With polonius it is possible to remove this lifetime transmutation and just have
// the correct lifetime of the reference inferred based on which branch is taken
let slice: &'a [u8] = unsafe { slice::from_raw_parts(slice.as_ptr(), slice.len()) };
Poll::Ready(Ok(slice))
}
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
Poll::Pending => {
this.reader = Some(reader);
Expand Down

0 comments on commit c179201

Please sign in to comment.