Skip to content

Commit e002c6c

Browse files
authored
Rollup merge of #155684 - bushrat011899:blanket_io_seek_for_ref, r=jhpratt
Generalize IO Traits for `Arc<T>` where `&T: IoTrait` ACP: rust-lang/libs-team#755 Tracking issue: #154046 Related: #94744 ## Description After experimenting with #155625, I noticed `Seek` and `SeekFrom` can almost be moved to `core::io`. Unfortunately, the implementation of `Seek` for `Arc<File>` is a blocker for such a move, since `Arc` is not a fundamental type. This PR attempts to resolve this potential blocker by replacing the implementation with a more general alternative. An internal trait `IoHandle` has been added which types can implement to opt-in to `Read`/`Write`/`Seek` implementations for `Arc<Self>` as long as `&Self` implements said trait. Note that `BufRead` is excluded as the signature for `fill_buf` would require returning from a temporary. Since this "blanket" implementation only applies to a single type which already implements the same traits, I believe this should have no user-facing impact. If this PR was merged, #134190 could be replaced with a 2 line PR: ```rust impl IoHandle for TcpStream {} impl IoHandle for UnixStream {} ``` Likewise for any other types, a table of which can be found [here](rust-lang/libs-team#504 (comment)). This is out of scope for this PR to avoid the need for an ACP. --- ## Notes * See [this comment](#154046 (comment)) for further details. * No AI tooling of any kind was used during the creation of this PR.
2 parents d493b7c + 7ba9478 commit e002c6c

3 files changed

Lines changed: 136 additions & 53 deletions

File tree

library/std/src/fs.rs

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ use crate::ffi::OsString;
4545
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
4646
use crate::path::{Path, PathBuf};
4747
use crate::sealed::Sealed;
48-
use crate::sync::Arc;
4948
use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, fs as fs_imp};
5049
use crate::time::SystemTime;
5150
use crate::{error, fmt};
@@ -1541,58 +1540,7 @@ impl Seek for File {
15411540
(&*self).stream_position()
15421541
}
15431542
}
1544-
1545-
#[stable(feature = "io_traits_arc", since = "1.73.0")]
1546-
impl Read for Arc<File> {
1547-
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1548-
(&**self).read(buf)
1549-
}
1550-
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
1551-
(&**self).read_vectored(bufs)
1552-
}
1553-
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
1554-
(&**self).read_buf(cursor)
1555-
}
1556-
#[inline]
1557-
fn is_read_vectored(&self) -> bool {
1558-
(&**self).is_read_vectored()
1559-
}
1560-
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
1561-
(&**self).read_to_end(buf)
1562-
}
1563-
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
1564-
(&**self).read_to_string(buf)
1565-
}
1566-
}
1567-
#[stable(feature = "io_traits_arc", since = "1.73.0")]
1568-
impl Write for Arc<File> {
1569-
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1570-
(&**self).write(buf)
1571-
}
1572-
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
1573-
(&**self).write_vectored(bufs)
1574-
}
1575-
#[inline]
1576-
fn is_write_vectored(&self) -> bool {
1577-
(&**self).is_write_vectored()
1578-
}
1579-
#[inline]
1580-
fn flush(&mut self) -> io::Result<()> {
1581-
(&**self).flush()
1582-
}
1583-
}
1584-
#[stable(feature = "io_traits_arc", since = "1.73.0")]
1585-
impl Seek for Arc<File> {
1586-
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
1587-
(&**self).seek(pos)
1588-
}
1589-
fn stream_len(&mut self) -> io::Result<u64> {
1590-
(&**self).stream_len()
1591-
}
1592-
fn stream_position(&mut self) -> io::Result<u64> {
1593-
(&**self).stream_position()
1594-
}
1595-
}
1543+
impl crate::io::IoHandle for File {}
15961544

15971545
impl Dir {
15981546
/// Attempts to open a directory at `path` in read-only mode.

library/std/src/io/impls.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod tests;
44
use crate::alloc::Allocator;
55
use crate::collections::VecDeque;
66
use crate::io::{self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
7+
use crate::sync::Arc;
78
use crate::{cmp, fmt, mem, str};
89

910
// =============================================================================
@@ -715,3 +716,122 @@ impl<'a> io::Write for core::io::BorrowedCursor<'a> {
715716
Ok(())
716717
}
717718
}
719+
720+
#[stable(feature = "io_traits_arc", since = "1.73.0")]
721+
impl<R: Read + ?Sized> Read for Arc<R>
722+
where
723+
for<'a> &'a R: Read,
724+
R: crate::io::IoHandle,
725+
{
726+
#[inline]
727+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
728+
(&**self).read(buf)
729+
}
730+
731+
#[inline]
732+
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
733+
(&**self).read_buf(cursor)
734+
}
735+
736+
#[inline]
737+
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
738+
(&**self).read_vectored(bufs)
739+
}
740+
741+
#[inline]
742+
fn is_read_vectored(&self) -> bool {
743+
(&**self).is_read_vectored()
744+
}
745+
746+
#[inline]
747+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
748+
(&**self).read_to_end(buf)
749+
}
750+
751+
#[inline]
752+
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
753+
(&**self).read_to_string(buf)
754+
}
755+
756+
#[inline]
757+
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
758+
(&**self).read_exact(buf)
759+
}
760+
761+
#[inline]
762+
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
763+
(&**self).read_buf_exact(cursor)
764+
}
765+
}
766+
#[stable(feature = "io_traits_arc", since = "1.73.0")]
767+
impl<W: Write + ?Sized> Write for Arc<W>
768+
where
769+
for<'a> &'a W: Write,
770+
W: crate::io::IoHandle,
771+
{
772+
#[inline]
773+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
774+
(&**self).write(buf)
775+
}
776+
777+
#[inline]
778+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
779+
(&**self).write_vectored(bufs)
780+
}
781+
782+
#[inline]
783+
fn is_write_vectored(&self) -> bool {
784+
(&**self).is_write_vectored()
785+
}
786+
787+
#[inline]
788+
fn flush(&mut self) -> io::Result<()> {
789+
(&**self).flush()
790+
}
791+
792+
#[inline]
793+
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
794+
(&**self).write_all(buf)
795+
}
796+
797+
#[inline]
798+
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
799+
(&**self).write_all_vectored(bufs)
800+
}
801+
802+
#[inline]
803+
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
804+
(&**self).write_fmt(fmt)
805+
}
806+
}
807+
#[stable(feature = "io_traits_arc", since = "1.73.0")]
808+
impl<S: Seek + ?Sized> Seek for Arc<S>
809+
where
810+
for<'a> &'a S: Seek,
811+
S: crate::io::IoHandle,
812+
{
813+
#[inline]
814+
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
815+
(&**self).seek(pos)
816+
}
817+
818+
#[inline]
819+
fn rewind(&mut self) -> io::Result<()> {
820+
(&**self).rewind()
821+
}
822+
823+
#[inline]
824+
fn stream_len(&mut self) -> io::Result<u64> {
825+
(&**self).stream_len()
826+
}
827+
828+
#[inline]
829+
fn stream_position(&mut self) -> io::Result<u64> {
830+
(&**self).stream_position()
831+
}
832+
833+
#[inline]
834+
fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
835+
(&**self).seek_relative(offset)
836+
}
837+
}

library/std/src/io/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,6 +2226,21 @@ pub enum SeekFrom {
22262226
Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
22272227
}
22282228

2229+
/// Marks that a type `T` can have IO traits such as [`Seek`], [`Write`], etc. automatically
2230+
/// implemented for handle types like [`Arc`][arc] as well.
2231+
///
2232+
/// This trait should only be implemented for types where `<&T as Trait>::method(&mut &value, ..)`
2233+
/// would be identical to `<T as Trait>::method(&mut value, ..)`.
2234+
///
2235+
/// [`File`][file] passes this test, as operations on `&File` and `File` both affect
2236+
/// the same underlying file.
2237+
/// `[u8]` fails, because any modification to `&mut &[u8]` would only affect a temporary
2238+
/// and be lost after the method has been called.
2239+
///
2240+
/// [file]: crate::fs::File
2241+
/// [arc]: crate::sync::Arc
2242+
pub(crate) trait IoHandle {}
2243+
22292244
fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> Result<usize> {
22302245
let mut read = 0;
22312246
loop {

0 commit comments

Comments
 (0)