Skip to content

Commit cae6f2d

Browse files
committed
remove default read impl
1 parent fc7c10d commit cae6f2d

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

text/0000-read-buf.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,6 @@ The `Read` trait uses this type in some of its methods:
376376

377377
```rust
378378
pub trait Read {
379-
/// The existing `read` method gains a default implementation that delegates to `read_buf`.
380-
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
381-
let mut buf = ReadBuf::new(buf);
382-
self.read_buf(&mut buf)?;
383-
Ok(buf.written().len())
384-
}
385-
386379
/// Pull some bytes from this source into the specified buffer.
387380
///
388381
/// This is equivalent to the `read` method, except that it is passed a `ReadBuf` rather than `[u8]` to allow use
@@ -411,12 +404,21 @@ Thinking back to the `BrokenReader` in the motivation section, the worst an impl
411404
unsound unsafe code) is to fail to actually write useful data into the buffer. Code using a `BrokenReader` may see bad
412405
data in the buffer, but the bad data at least has defined contents now!
413406

414-
Note that `read` and `read_buf` have default implementations that delegate to each other. `read_buf` must have a default
415-
implementation for backwards compatibility, and we want `read` to have a default implementation so that `Read`
416-
implementations can simply contain code for `read_buf`. This cycle does mean that a trivial `Read` implementation of
417-
`impl Read for Foo {}` will compile but calls will infinitely recurse. We would ideally create a lint that exactly one
418-
of the two methods is implemented, but that is not a hard requirement. Such an implementation is pretty obviously
419-
ridiculous and this hopefully shouldn't be a huge problem in practice.
407+
Note that `read` is still a required method of the `Read` trait. It can be easily written to delegate to read_buf:
408+
409+
```rust
410+
impl Read for SomeReader {
411+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
412+
let mut buf = ReadBuf::new(buf);
413+
self.read_buf(&mut buf)?;
414+
Ok(buf.filled().len())
415+
}
416+
417+
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
418+
...
419+
}
420+
}
421+
```
420422

421423
Some of `Read`'s convenience methods will be modified to take advantage of `read_buf`, and some new convenience methods
422424
will be added:
@@ -508,6 +510,8 @@ where
508510
}
509511
```
510512

513+
The existing `std::io::Initializer` type and `Read::initializer` method will be removed.
514+
511515
Vectored writes use a similar API:
512516

513517
```rust
@@ -622,5 +626,6 @@ Some of the complexity in the implementation of `read_to_end` above is due to ha
622626
`Vec<u8>`'s spare capacity has already been initialized between iterations of the read loop. There is probably some kind
623627
of abstraction that could be defined to encapsulate that logic.
624628

625-
Should `read` gain a default implementation? It avoids forcing boilerplate for implementations that use `read_buf` as
626-
the "main" method, but does allow the broken empty implementation.
629+
Users shouldn't be required to manually write a version of `read` that delegates to `read_buf`. We should be able to
630+
eventually add a default implementation of `read`, along with a requirement that one of `read` and `read_buf` must be
631+
overridden.

0 commit comments

Comments
 (0)