Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stablize anonymous pipe #137793

Merged
merged 2 commits into from
Mar 17, 2025
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
2 changes: 1 addition & 1 deletion library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ pub use self::error::RawOsError;
pub use self::error::SimpleMessage;
#[unstable(feature = "io_const_error", issue = "133448")]
pub use self::error::const_error;
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
pub use self::pipe::{PipeReader, PipeWriter, pipe};
#[stable(feature = "is_terminal", since = "1.70.0")]
pub use self::stdio::IsTerminal;
Expand Down
46 changes: 34 additions & 12 deletions library/std/src/io/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::io;
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
use crate::sys_common::{FromInner, IntoInner};

/// Create an anonymous pipe.
///
Expand Down Expand Up @@ -40,7 +41,6 @@ use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
/// # Examples
///
/// ```no_run
/// #![feature(anonymous_pipe)]
/// # #[cfg(miri)] fn main() {}
/// # #[cfg(not(miri))]
/// # fn main() -> std::io::Result<()> {
Expand All @@ -67,29 +67,52 @@ use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
/// ```
/// [changes]: io#platform-specific-behavior
/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
}

/// Read end of an anonymous pipe.
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
#[derive(Debug)]
pub struct PipeReader(pub(crate) AnonPipe);

/// Write end of an anonymous pipe.
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
#[derive(Debug)]
pub struct PipeWriter(pub(crate) AnonPipe);

impl FromInner<AnonPipe> for PipeReader {
fn from_inner(inner: AnonPipe) -> Self {
Self(inner)
}
}

impl IntoInner<AnonPipe> for PipeReader {
fn into_inner(self) -> AnonPipe {
self.0
}
}

impl FromInner<AnonPipe> for PipeWriter {
fn from_inner(inner: AnonPipe) -> Self {
Self(inner)
}
}

impl IntoInner<AnonPipe> for PipeWriter {
fn into_inner(self) -> AnonPipe {
self.0
}
}

impl PipeReader {
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
///
/// # Examples
///
/// ```no_run
/// #![feature(anonymous_pipe)]
/// # #[cfg(miri)] fn main() {}
/// # #[cfg(not(miri))]
/// # fn main() -> std::io::Result<()> {
Expand Down Expand Up @@ -137,7 +160,7 @@ impl PipeReader {
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
pub fn try_clone(&self) -> io::Result<Self> {
self.0.try_clone().map(Self)
}
Expand All @@ -149,7 +172,6 @@ impl PipeWriter {
/// # Examples
///
/// ```no_run
/// #![feature(anonymous_pipe)]
/// # #[cfg(miri)] fn main() {}
/// # #[cfg(not(miri))]
/// # fn main() -> std::io::Result<()> {
Expand Down Expand Up @@ -177,13 +199,13 @@ impl PipeWriter {
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
pub fn try_clone(&self) -> io::Result<Self> {
self.0.try_clone().map(Self)
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl io::Read for &PipeReader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
Expand All @@ -203,7 +225,7 @@ impl io::Read for &PipeReader {
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl io::Read for PipeReader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
Expand All @@ -223,7 +245,7 @@ impl io::Read for PipeReader {
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl io::Write for &PipeWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
Expand All @@ -241,7 +263,7 @@ impl io::Write for &PipeWriter {
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl io::Write for PipeWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
Expand Down
45 changes: 44 additions & 1 deletion library/std/src/os/fd/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ use crate::mem::ManuallyDrop;
target_os = "trusty"
)))]
use crate::sys::cvt;
use crate::sys_common::FromInner;
#[cfg(not(target_os = "trusty"))]
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::sys_common::{AsInner, IntoInner};
use crate::{fmt, io};

type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
Expand Down Expand Up @@ -504,3 +505,45 @@ impl<'a> AsFd for io::StderrLock<'a> {
unsafe { BorrowedFd::borrow_raw(2) }
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsFd for io::PipeReader {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<io::PipeReader> for OwnedFd {
fn from(pipe: io::PipeReader) -> Self {
pipe.0.into_inner()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsFd for io::PipeWriter {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<io::PipeWriter> for OwnedFd {
fn from(pipe: io::PipeWriter) -> Self {
pipe.0.into_inner()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<OwnedFd> for io::PipeReader {
fn from(owned_fd: OwnedFd) -> Self {
Self(FromInner::from_inner(owned_fd))
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<OwnedFd> for io::PipeWriter {
fn from(owned_fd: OwnedFd) -> Self {
Self(FromInner::from_inner(owned_fd))
}
}
43 changes: 43 additions & 0 deletions library/std/src/os/fd/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::os::unix::io::AsFd;
use crate::os::unix::io::OwnedFd;
#[cfg(target_os = "wasi")]
use crate::os::wasi::io::OwnedFd;
use crate::sys_common::FromInner;
#[cfg(not(target_os = "trusty"))]
use crate::sys_common::{AsInner, IntoInner};

Expand Down Expand Up @@ -284,3 +285,45 @@ impl<T: AsRawFd> AsRawFd for Box<T> {
(**self).as_raw_fd()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsRawFd for io::PipeReader {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl FromRawFd for io::PipeReader {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) })
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl IntoRawFd for io::PipeReader {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsRawFd for io::PipeWriter {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl FromRawFd for io::PipeWriter {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) })
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl IntoRawFd for io::PipeWriter {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}
42 changes: 42 additions & 0 deletions library/std/src/os/windows/io/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,3 +660,45 @@ impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
join_handle.into_inner().into_handle().into_inner()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsHandle for io::PipeReader {
fn as_handle(&self) -> BorrowedHandle<'_> {
self.0.as_handle()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<io::PipeReader> for OwnedHandle {
fn from(pipe: io::PipeReader) -> Self {
pipe.into_inner().into_inner()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsHandle for io::PipeWriter {
fn as_handle(&self) -> BorrowedHandle<'_> {
self.0.as_handle()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<io::PipeWriter> for OwnedHandle {
fn from(pipe: io::PipeWriter) -> Self {
pipe.into_inner().into_inner()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<OwnedHandle> for io::PipeReader {
fn from(owned_handle: OwnedHandle) -> Self {
Self::from_inner(FromInner::from_inner(owned_handle))
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<OwnedHandle> for io::PipeWriter {
fn from(owned_handle: OwnedHandle) -> Self {
Self::from_inner(FromInner::from_inner(owned_handle))
}
}
42 changes: 42 additions & 0 deletions library/std/src/os/windows/io/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,45 @@ impl IntoRawSocket for net::UdpSocket {
self.into_inner().into_socket().into_inner().into_raw_socket()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsRawHandle for io::PipeReader {
fn as_raw_handle(&self) -> RawHandle {
self.0.as_raw_handle()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl FromRawHandle for io::PipeReader {
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl IntoRawHandle for io::PipeReader {
fn into_raw_handle(self) -> RawHandle {
self.0.into_raw_handle()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl AsRawHandle for io::PipeWriter {
fn as_raw_handle(&self) -> RawHandle {
self.0.as_raw_handle()
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl FromRawHandle for io::PipeWriter {
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl IntoRawHandle for io::PipeWriter {
fn into_raw_handle(self) -> RawHandle {
self.0.into_raw_handle()
}
}
14 changes: 14 additions & 0 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,20 @@ impl From<io::Stderr> for Stdio {
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<io::PipeWriter> for Stdio {
fn from(pipe: io::PipeWriter) -> Self {
Stdio::from_inner(pipe.into_inner().into())
}
}

#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
impl From<io::PipeReader> for Stdio {
fn from(pipe: io::PipeReader) -> Self {
Stdio::from_inner(pipe.into_inner().into())
}
}

/// Describes the result of a process after it has terminated.
///
/// This `struct` is used to represent the exit status or other termination of a child process.
Expand Down
Loading
Loading