Skip to content

Commit c55af41

Browse files
Rollup merge of #111074 - WaffleLapkin:🌟unsizes_your_buf_reader🌟, r=Amanieu
Relax implicit `T: Sized` bounds on `BufReader<T>`, `BufWriter<T>` and `LineWriter<T>` TL;DR: ```diff,rust -pub struct BufReader<R> { /* ... */ } +pub struct BufReader<R: ?Sized> { /* ... */ } -pub struct BufWriter<W: Write> { /* ... */ } +pub struct BufWriter<W: ?Sized + Write> { /* ... */ } -pub struct LineWriter<W: Write> { /* ... */ } +pub struct LineWriter<W: ?Sized + Write> { /* ... */ } ``` This allows using `&mut BufReader<dyn Read>`, for example. **This is an insta-stable change**.
2 parents 6a94e87 + 29302a2 commit c55af41

File tree

7 files changed

+118
-111
lines changed

7 files changed

+118
-111
lines changed

library/std/src/io/buffered/bufreader.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ use buffer::Buffer;
4747
/// }
4848
/// ```
4949
#[stable(feature = "rust1", since = "1.0.0")]
50-
pub struct BufReader<R> {
51-
inner: R,
50+
pub struct BufReader<R: ?Sized> {
5251
buf: Buffer,
52+
inner: R,
5353
}
5454

5555
impl<R: Read> BufReader<R> {
@@ -95,7 +95,7 @@ impl<R: Read> BufReader<R> {
9595
}
9696
}
9797

98-
impl<R> BufReader<R> {
98+
impl<R: ?Sized> BufReader<R> {
9999
/// Gets a reference to the underlying reader.
100100
///
101101
/// It is inadvisable to directly read from the underlying reader.
@@ -213,7 +213,10 @@ impl<R> BufReader<R> {
213213
/// }
214214
/// ```
215215
#[stable(feature = "rust1", since = "1.0.0")]
216-
pub fn into_inner(self) -> R {
216+
pub fn into_inner(self) -> R
217+
where
218+
R: Sized,
219+
{
217220
self.inner
218221
}
219222

@@ -226,13 +229,13 @@ impl<R> BufReader<R> {
226229

227230
// This is only used by a test which asserts that the initialization-tracking is correct.
228231
#[cfg(test)]
229-
impl<R> BufReader<R> {
232+
impl<R: ?Sized> BufReader<R> {
230233
pub fn initialized(&self) -> usize {
231234
self.buf.initialized()
232235
}
233236
}
234237

235-
impl<R: Seek> BufReader<R> {
238+
impl<R: ?Sized + Seek> BufReader<R> {
236239
/// Seeks relative to the current position. If the new position lies within the buffer,
237240
/// the buffer will not be flushed, allowing for more efficient seeks.
238241
/// This method does not return the location of the underlying reader, so the caller
@@ -257,7 +260,7 @@ impl<R: Seek> BufReader<R> {
257260
}
258261

259262
#[stable(feature = "rust1", since = "1.0.0")]
260-
impl<R: Read> Read for BufReader<R> {
263+
impl<R: ?Sized + Read> Read for BufReader<R> {
261264
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
262265
// If we don't have any buffered data and we're doing a massive read
263266
// (larger than our internal buffer), bypass our internal buffer
@@ -371,7 +374,7 @@ impl<R: Read> Read for BufReader<R> {
371374
}
372375

373376
#[stable(feature = "rust1", since = "1.0.0")]
374-
impl<R: Read> BufRead for BufReader<R> {
377+
impl<R: ?Sized + Read> BufRead for BufReader<R> {
375378
fn fill_buf(&mut self) -> io::Result<&[u8]> {
376379
self.buf.fill_buf(&mut self.inner)
377380
}
@@ -384,11 +387,11 @@ impl<R: Read> BufRead for BufReader<R> {
384387
#[stable(feature = "rust1", since = "1.0.0")]
385388
impl<R> fmt::Debug for BufReader<R>
386389
where
387-
R: fmt::Debug,
390+
R: ?Sized + fmt::Debug,
388391
{
389392
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
390393
fmt.debug_struct("BufReader")
391-
.field("reader", &self.inner)
394+
.field("reader", &&self.inner)
392395
.field(
393396
"buffer",
394397
&format_args!("{}/{}", self.buf.filled() - self.buf.pos(), self.capacity()),
@@ -398,7 +401,7 @@ where
398401
}
399402

400403
#[stable(feature = "rust1", since = "1.0.0")]
401-
impl<R: Seek> Seek for BufReader<R> {
404+
impl<R: ?Sized + Seek> Seek for BufReader<R> {
402405
/// Seek to an offset, in bytes, in the underlying reader.
403406
///
404407
/// The position used for seeking with <code>[SeekFrom::Current]\(_)</code> is the
@@ -491,7 +494,7 @@ impl<R: Seek> Seek for BufReader<R> {
491494
}
492495
}
493496

494-
impl<T> SizeHint for BufReader<T> {
497+
impl<T: ?Sized> SizeHint for BufReader<T> {
495498
#[inline]
496499
fn lower_bound(&self) -> usize {
497500
SizeHint::lower_bound(self.get_ref()) + self.buffer().len()

library/std/src/io/buffered/bufwriter.rs

+70-68
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ use crate::ptr;
6767
/// [`TcpStream`]: crate::net::TcpStream
6868
/// [`flush`]: BufWriter::flush
6969
#[stable(feature = "rust1", since = "1.0.0")]
70-
pub struct BufWriter<W: Write> {
71-
inner: W,
70+
pub struct BufWriter<W: ?Sized + Write> {
7271
// The buffer. Avoid using this like a normal `Vec` in common code paths.
7372
// That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
7473
// methods that require bounds checking or the like. This makes an enormous
@@ -78,6 +77,7 @@ pub struct BufWriter<W: Write> {
7877
// write the buffered data a second time in BufWriter's destructor. This
7978
// flag tells the Drop impl if it should skip the flush.
8079
panicked: bool,
80+
inner: W,
8181
}
8282

8383
impl<W: Write> BufWriter<W> {
@@ -115,6 +115,69 @@ impl<W: Write> BufWriter<W> {
115115
BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false }
116116
}
117117

118+
/// Unwraps this `BufWriter<W>`, returning the underlying writer.
119+
///
120+
/// The buffer is written out before returning the writer.
121+
///
122+
/// # Errors
123+
///
124+
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
125+
///
126+
/// # Examples
127+
///
128+
/// ```no_run
129+
/// use std::io::BufWriter;
130+
/// use std::net::TcpStream;
131+
///
132+
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
133+
///
134+
/// // unwrap the TcpStream and flush the buffer
135+
/// let stream = buffer.into_inner().unwrap();
136+
/// ```
137+
#[stable(feature = "rust1", since = "1.0.0")]
138+
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
139+
match self.flush_buf() {
140+
Err(e) => Err(IntoInnerError::new(self, e)),
141+
Ok(()) => Ok(self.into_parts().0),
142+
}
143+
}
144+
145+
/// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
146+
/// unwritten data.
147+
///
148+
/// If the underlying writer panicked, it is not known what portion of the data was written.
149+
/// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
150+
/// contents can still be recovered).
151+
///
152+
/// `into_parts` makes no attempt to flush data and cannot fail.
153+
///
154+
/// # Examples
155+
///
156+
/// ```
157+
/// use std::io::{BufWriter, Write};
158+
///
159+
/// let mut buffer = [0u8; 10];
160+
/// let mut stream = BufWriter::new(buffer.as_mut());
161+
/// write!(stream, "too much data").unwrap();
162+
/// stream.flush().expect_err("it doesn't fit");
163+
/// let (recovered_writer, buffered_data) = stream.into_parts();
164+
/// assert_eq!(recovered_writer.len(), 0);
165+
/// assert_eq!(&buffered_data.unwrap(), b"ata");
166+
/// ```
167+
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
168+
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
169+
let buf = mem::take(&mut self.buf);
170+
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
171+
172+
// SAFETY: forget(self) prevents double dropping inner
173+
let inner = unsafe { ptr::read(&self.inner) };
174+
mem::forget(self);
175+
176+
(inner, buf)
177+
}
178+
}
179+
180+
impl<W: ?Sized + Write> BufWriter<W> {
118181
/// Send data in our local buffer into the inner writer, looping as
119182
/// necessary until either it's all been sent or an error occurs.
120183
///
@@ -284,67 +347,6 @@ impl<W: Write> BufWriter<W> {
284347
self.buf.capacity()
285348
}
286349

287-
/// Unwraps this `BufWriter<W>`, returning the underlying writer.
288-
///
289-
/// The buffer is written out before returning the writer.
290-
///
291-
/// # Errors
292-
///
293-
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
294-
///
295-
/// # Examples
296-
///
297-
/// ```no_run
298-
/// use std::io::BufWriter;
299-
/// use std::net::TcpStream;
300-
///
301-
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
302-
///
303-
/// // unwrap the TcpStream and flush the buffer
304-
/// let stream = buffer.into_inner().unwrap();
305-
/// ```
306-
#[stable(feature = "rust1", since = "1.0.0")]
307-
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
308-
match self.flush_buf() {
309-
Err(e) => Err(IntoInnerError::new(self, e)),
310-
Ok(()) => Ok(self.into_parts().0),
311-
}
312-
}
313-
314-
/// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
315-
/// unwritten data.
316-
///
317-
/// If the underlying writer panicked, it is not known what portion of the data was written.
318-
/// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
319-
/// contents can still be recovered).
320-
///
321-
/// `into_parts` makes no attempt to flush data and cannot fail.
322-
///
323-
/// # Examples
324-
///
325-
/// ```
326-
/// use std::io::{BufWriter, Write};
327-
///
328-
/// let mut buffer = [0u8; 10];
329-
/// let mut stream = BufWriter::new(buffer.as_mut());
330-
/// write!(stream, "too much data").unwrap();
331-
/// stream.flush().expect_err("it doesn't fit");
332-
/// let (recovered_writer, buffered_data) = stream.into_parts();
333-
/// assert_eq!(recovered_writer.len(), 0);
334-
/// assert_eq!(&buffered_data.unwrap(), b"ata");
335-
/// ```
336-
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
337-
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
338-
let buf = mem::take(&mut self.buf);
339-
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
340-
341-
// SAFETY: forget(self) prevents double dropping inner
342-
let inner = unsafe { ptr::read(&self.inner) };
343-
mem::forget(self);
344-
345-
(inner, buf)
346-
}
347-
348350
// Ensure this function does not get inlined into `write`, so that it
349351
// remains inlineable and its common path remains as short as possible.
350352
// If this function ends up being called frequently relative to `write`,
@@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked {
511513
}
512514

513515
#[stable(feature = "rust1", since = "1.0.0")]
514-
impl<W: Write> Write for BufWriter<W> {
516+
impl<W: ?Sized + Write> Write for BufWriter<W> {
515517
#[inline]
516518
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
517519
// Use < instead of <= to avoid a needless trip through the buffer in some cases.
@@ -640,20 +642,20 @@ impl<W: Write> Write for BufWriter<W> {
640642
}
641643

642644
#[stable(feature = "rust1", since = "1.0.0")]
643-
impl<W: Write> fmt::Debug for BufWriter<W>
645+
impl<W: ?Sized + Write> fmt::Debug for BufWriter<W>
644646
where
645647
W: fmt::Debug,
646648
{
647649
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
648650
fmt.debug_struct("BufWriter")
649-
.field("writer", &self.inner)
651+
.field("writer", &&self.inner)
650652
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
651653
.finish()
652654
}
653655
}
654656

655657
#[stable(feature = "rust1", since = "1.0.0")]
656-
impl<W: Write + Seek> Seek for BufWriter<W> {
658+
impl<W: ?Sized + Write + Seek> Seek for BufWriter<W> {
657659
/// Seek to the offset, in bytes, in the underlying writer.
658660
///
659661
/// Seeking always writes out the internal buffer before seeking.
@@ -664,7 +666,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
664666
}
665667

666668
#[stable(feature = "rust1", since = "1.0.0")]
667-
impl<W: Write> Drop for BufWriter<W> {
669+
impl<W: ?Sized + Write> Drop for BufWriter<W> {
668670
fn drop(&mut self) {
669671
if !self.panicked {
670672
// dtors should not panic, so we ignore a failed flush

library/std/src/io/buffered/linewriter.rs

+26-24
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSli
6464
/// }
6565
/// ```
6666
#[stable(feature = "rust1", since = "1.0.0")]
67-
pub struct LineWriter<W: Write> {
67+
pub struct LineWriter<W: ?Sized + Write> {
6868
inner: BufWriter<W>,
6969
}
7070

@@ -109,27 +109,6 @@ impl<W: Write> LineWriter<W> {
109109
LineWriter { inner: BufWriter::with_capacity(capacity, inner) }
110110
}
111111

112-
/// Gets a reference to the underlying writer.
113-
///
114-
/// # Examples
115-
///
116-
/// ```no_run
117-
/// use std::fs::File;
118-
/// use std::io::LineWriter;
119-
///
120-
/// fn main() -> std::io::Result<()> {
121-
/// let file = File::create("poem.txt")?;
122-
/// let file = LineWriter::new(file);
123-
///
124-
/// let reference = file.get_ref();
125-
/// Ok(())
126-
/// }
127-
/// ```
128-
#[stable(feature = "rust1", since = "1.0.0")]
129-
pub fn get_ref(&self) -> &W {
130-
self.inner.get_ref()
131-
}
132-
133112
/// Gets a mutable reference to the underlying writer.
134113
///
135114
/// Caution must be taken when calling methods on the mutable reference
@@ -184,8 +163,31 @@ impl<W: Write> LineWriter<W> {
184163
}
185164
}
186165

166+
impl<W: ?Sized + Write> LineWriter<W> {
167+
/// Gets a reference to the underlying writer.
168+
///
169+
/// # Examples
170+
///
171+
/// ```no_run
172+
/// use std::fs::File;
173+
/// use std::io::LineWriter;
174+
///
175+
/// fn main() -> std::io::Result<()> {
176+
/// let file = File::create("poem.txt")?;
177+
/// let file = LineWriter::new(file);
178+
///
179+
/// let reference = file.get_ref();
180+
/// Ok(())
181+
/// }
182+
/// ```
183+
#[stable(feature = "rust1", since = "1.0.0")]
184+
pub fn get_ref(&self) -> &W {
185+
self.inner.get_ref()
186+
}
187+
}
188+
187189
#[stable(feature = "rust1", since = "1.0.0")]
188-
impl<W: Write> Write for LineWriter<W> {
190+
impl<W: ?Sized + Write> Write for LineWriter<W> {
189191
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
190192
LineWriterShim::new(&mut self.inner).write(buf)
191193
}
@@ -216,7 +218,7 @@ impl<W: Write> Write for LineWriter<W> {
216218
}
217219

218220
#[stable(feature = "rust1", since = "1.0.0")]
219-
impl<W: Write> fmt::Debug for LineWriter<W>
221+
impl<W: ?Sized + Write> fmt::Debug for LineWriter<W>
220222
where
221223
W: fmt::Debug,
222224
{

library/std/src/io/buffered/linewritershim.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ use crate::sys_common::memchr;
1111
/// `BufWriters` to be temporarily given line-buffering logic; this is what
1212
/// enables Stdout to be alternately in line-buffered or block-buffered mode.
1313
#[derive(Debug)]
14-
pub struct LineWriterShim<'a, W: Write> {
14+
pub struct LineWriterShim<'a, W: ?Sized + Write> {
1515
buffer: &'a mut BufWriter<W>,
1616
}
1717

18-
impl<'a, W: Write> LineWriterShim<'a, W> {
18+
impl<'a, W: ?Sized + Write> LineWriterShim<'a, W> {
1919
pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
2020
Self { buffer }
2121
}
@@ -49,7 +49,7 @@ impl<'a, W: Write> LineWriterShim<'a, W> {
4949
}
5050
}
5151

52-
impl<'a, W: Write> Write for LineWriterShim<'a, W> {
52+
impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> {
5353
/// Write some data into this BufReader with line buffering. This means
5454
/// that, if any newlines are present in the data, the data up to the last
5555
/// newline is sent directly to the underlying writer, and data after it

0 commit comments

Comments
 (0)