diff --git a/tokio/src/io/util/read_to_end.rs b/tokio/src/io/util/read_to_end.rs index dff7d66d0c6..f4a564d7dd4 100644 --- a/tokio/src/io/util/read_to_end.rs +++ b/tokio/src/io/util/read_to_end.rs @@ -1,4 +1,4 @@ -use crate::io::util::vec_with_initialized::{into_read_buf_parts, VecWithInitialized}; +use crate::io::util::vec_with_initialized::{into_read_buf_parts, VecU8, VecWithInitialized}; use crate::io::AsyncRead; use pin_project_lite::pin_project; @@ -28,16 +28,15 @@ pub(crate) fn read_to_end<'a, R>(reader: &'a mut R, buffer: &'a mut Vec) -> where R: AsyncRead + Unpin + ?Sized, { - // SAFETY: The generic type on VecWithInitialized is &mut Vec. ReadToEnd { reader, - buf: unsafe { VecWithInitialized::new(buffer) }, + buf: VecWithInitialized::new(buffer), read: 0, _pin: PhantomPinned, } } -pub(super) fn read_to_end_internal>, R: AsyncRead + ?Sized>( +pub(super) fn read_to_end_internal( buf: &mut VecWithInitialized, mut reader: Pin<&mut R>, num_read: &mut usize, @@ -58,7 +57,7 @@ pub(super) fn read_to_end_internal>, R: AsyncRead + ?Sized>( /// Tries to read from the provided AsyncRead. /// /// The length of the buffer is increased by the number of bytes read. -fn poll_read_to_end>, R: AsyncRead + ?Sized>( +fn poll_read_to_end( buf: &mut VecWithInitialized, read: Pin<&mut R>, cx: &mut Context<'_>, diff --git a/tokio/src/io/util/read_to_string.rs b/tokio/src/io/util/read_to_string.rs index 215ead370d8..2c17383c6e7 100644 --- a/tokio/src/io/util/read_to_string.rs +++ b/tokio/src/io/util/read_to_string.rs @@ -38,10 +38,9 @@ where R: AsyncRead + ?Sized + Unpin, { let buf = mem::replace(string, String::new()).into_bytes(); - // SAFETY: The generic type of the VecWithInitialized is Vec. ReadToString { reader, - buf: unsafe { VecWithInitialized::new(buf) }, + buf: VecWithInitialized::new(buf), output: string, read: 0, _pin: PhantomPinned, diff --git a/tokio/src/io/util/vec_with_initialized.rs b/tokio/src/io/util/vec_with_initialized.rs index ca24719dbf6..208cc939c1a 100644 --- a/tokio/src/io/util/vec_with_initialized.rs +++ b/tokio/src/io/util/vec_with_initialized.rs @@ -1,6 +1,19 @@ use crate::io::ReadBuf; use std::mem::MaybeUninit; +mod private { + pub trait Sealed {} + + impl Sealed for Vec {} + impl Sealed for &mut Vec {} +} + +/// A sealed trait that constrains the generic type parameter in `VecWithInitialized`. That struct's safety relies +/// on certain invariants upheld by `Vec`. +pub(crate) trait VecU8: AsMut> + private::Sealed {} + +impl VecU8 for Vec {} +impl VecU8 for &mut Vec {} /// This struct wraps a `Vec` or `&mut Vec`, combining it with a /// `num_initialized`, which keeps track of the number of initialized bytes /// in the unused capacity. @@ -28,10 +41,9 @@ impl VecWithInitialized> { impl VecWithInitialized where - V: AsMut>, + V: VecU8, { - /// Safety: The generic parameter `V` must be either `Vec` or `&mut Vec`. - pub(crate) unsafe fn new(mut vec: V) -> Self { + pub(crate) fn new(mut vec: V) -> Self { // SAFETY: The safety invariants of vector guarantee that the bytes up // to its length are initialized. Self {