File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -71,6 +71,9 @@ const unsafe fn new_cap<T>(cap: usize) -> Cap {
7171/// `Box<[T]>`, since `capacity()` won't yield the length.
7272#[ allow( missing_debug_implementations) ]
7373pub ( crate ) struct RawVec < T , A : Allocator = Global > {
74+ // FIXME: Despite "Its uninitialized memory is scratch space that it may use however it wants"
75+ // in `Vec`'s documentation, `BufWriter::flush_buf` relies on the scratch space being never
76+ // de-initialized by several methods.
7477 inner : RawVecInner < A > ,
7578 _marker : PhantomData < T > ,
7679}
@@ -83,6 +86,9 @@ pub(crate) struct RawVec<T, A: Allocator = Global> {
8386/// as most operations don't need the actual type, just its layout.
8487#[ allow( missing_debug_implementations) ]
8588struct RawVecInner < A : Allocator = Global > {
89+ // FIXME: Despite "Its uninitialized memory is scratch space that it may use however it wants"
90+ // in `Vec`'s documentation, `BufWriter::flush_buf` relies on the scratch space being never
91+ // de-initialized by several methods.
8692 ptr : Unique < u8 > ,
8793 /// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case.
8894 ///
Original file line number Diff line number Diff line change @@ -436,6 +436,9 @@ mod spec_extend;
436436#[ doc( alias = "list" ) ]
437437#[ doc( alias = "vector" ) ]
438438pub struct Vec < T , #[ unstable( feature = "allocator_api" , issue = "32838" ) ] A : Allocator = Global > {
439+ // FIXME: Despite "Its uninitialized memory is scratch space that it may use however it wants"
440+ // mentioned above, `BufWriter::flush_buf` relies on the sctach space being never
441+ // de-initialized by several methods.
439442 buf : RawVec < T , A > ,
440443 len : usize ,
441444}
Original file line number Diff line number Diff line change @@ -193,6 +193,13 @@ impl<W: ?Sized + Write> BufWriter<W> {
193193 /// `write`), any 0-length writes from `inner` must be reported as i/o
194194 /// errors from this method.
195195 pub ( in crate :: io) fn flush_buf ( & mut self ) -> io:: Result < ( ) > {
196+ // SAFETY: `<BufWriter as BufferedWriterSpec>::copy_from` requires that `self.buf`'s spare
197+ // capacity is preserved by this function. This function does not grow `self.buf` or
198+ // explicitly shrink its capacity; `Vec` guarantees that this is sufficient to avoid it
199+ // re-allocating. We never de-initialize the spare capacity of `self.buf` and we assume none
200+ // of the `Vec` methods used here will do so either, though nothing in `Vec`'s documentation
201+ // guarantees this.
202+
196203 /// Helper struct to ensure the buffer is updated after all the writes
197204 /// are complete. It tracks the number of written bytes and drains them
198205 /// all from the front of the buffer when dropped.
Original file line number Diff line number Diff line change @@ -221,7 +221,10 @@ impl<I: Write + ?Sized> BufferedWriterSpec for BufWriter<I> {
221221 let mut read_buf: BorrowedBuf < ' _ > = buf. spare_capacity_mut ( ) . into ( ) ;
222222
223223 if init {
224- // SAFETY: init is either 0 or the init_len from the previous iteration.
224+ // SAFETY: `init` is only true after `reader` initializes `read_buf`. `flush_buf`
225+ // guarantees that it won't cause any part of the spare capacity to become
226+ // uninitialized or cause `self.buf` to reallocate, so it is OK to persist this
227+ // across `flush_buf` calls.
225228 unsafe { read_buf. set_init ( ) } ;
226229 }
227230
You can’t perform that action at this time.
0 commit comments