diff --git a/tokio/src/io/util/fill_buf.rs b/tokio/src/io/util/fill_buf.rs index 98ae2ea6da5..3655c0153e7 100644 --- a/tokio/src/io/util/fill_buf.rs +++ b/tokio/src/io/util/fill_buf.rs @@ -34,15 +34,16 @@ impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for FillBuf<'a, R> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let me = self.project(); - // Due to a limitation in the borrow-checker, we cannot return the value - // directly on Ready. Once Rust starts using the polonius borrow checker, - // this can be simplified. let reader = me.reader.take().expect("Polled after completion."); match Pin::new(&mut *reader).poll_fill_buf(cx) { - Poll::Ready(_) => match Pin::new(reader).poll_fill_buf(cx) { - Poll::Ready(slice) => Poll::Ready(slice), - Poll::Pending => panic!("poll_fill_buf returned Pending while having data"), + Poll::Ready(Ok(slice)) => unsafe { + // Safety: This is necessary only due to a limitation in the + // borrow checker. Once Rust starts using the polonius borrow + // checker, this can be simplified. + let slice = std::mem::transmute::<&[u8], &'a [u8]>(slice); + Poll::Ready(Ok(slice)) }, + Poll::Ready(Err(err)) => Poll::Ready(Err(err)), Poll::Pending => { *me.reader = Some(reader); Poll::Pending diff --git a/tokio/tests/io_fill_buf.rs b/tokio/tests/io_fill_buf.rs new file mode 100644 index 00000000000..0b2ebd78fc7 --- /dev/null +++ b/tokio/tests/io_fill_buf.rs @@ -0,0 +1,34 @@ +#![warn(rust_2018_idioms)] +#![cfg(feature = "full")] + +use tempfile::NamedTempFile; +use tokio::fs::File; +use tokio::io::{AsyncBufReadExt, BufReader}; +use tokio_test::assert_ok; + +#[tokio::test] +async fn fill_buf_file() { + let file = NamedTempFile::new().unwrap(); + + assert_ok!(std::fs::write(file.path(), b"hello")); + + let file = assert_ok!(File::open(file.path()).await); + let mut file = BufReader::new(file); + + let mut contents = Vec::new(); + + loop { + let consumed = { + let buffer = assert_ok!(file.fill_buf().await); + if buffer.is_empty() { + break; + } + contents.extend_from_slice(buffer); + buffer.len() + }; + + file.consume(consumed); + } + + assert_eq!(contents, b"hello"); +}