8000 Use ManuallyDrop in BufWriter::into_parts by saethlin · Pull Request #127659 · rust-lang/rust · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Use ManuallyDrop in BufWriter::into_parts
  • Loading branch information
saethlin committed Jul 12, 2024
commit 7fc69436a1226b254b3b6f9ed8c6d54965e0cfbf
14 changes: 7 additions & 7 deletions library/std/src/io/buffered/bufwriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::fmt;
use crate::io::{
self, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
};
use crate::mem;
use crate::mem::{self, ManuallyDrop};
use crate::ptr;

/// Wraps a writer and buffers its output.
Expand Down Expand Up @@ -164,13 +164,13 @@ impl<W: Write> BufWriter<W> {
/// assert_eq!(&buffered_data.unwrap(), b"ata");
/// ```
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
let buf = mem::take(&mut self.buf);
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
pub fn into_parts(self) -> (W, Result<Vec<u8>, WriterPanicked>) {
let mut this = ManuallyDrop::new(self);
let buf = mem::take(&mut this.buf);
let buf = if !this.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };

// SAFETY: forget(self) prevents double dropping inner
let inner = unsafe { ptr::read(&self.inner) };
mem::forget(self);
// SAFETY: double-drops are prevented by putting `this` in a ManuallyDrop that is never dropped
let inner = unsafe { ptr::read(&this.inner) };

(inner, buf)
}
Expand Down
10 changes: 10 additions & 0 deletions library/std/src/io/buffered/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1067,3 +1067,13 @@ fn bufreader_full_initialize() {
// But we initialized the whole buffer!
assert_eq!(reader.initialized(), reader.capacity());
}

/// This is a regression test for https://github.com/rust-lang/rust/issues/127584.
#[test]
fn bufwriter_aliasing() {
use crate::io::{BufWriter, Cursor};
let mut v = vec![0; 1024];
let c = Cursor::new(&mut v);
let w = BufWriter::new(Box::new(c));
let _ = w.into_parts();
}
Loading
0