From 6bd68fcceb1d0708ce898fb92275119e2658d64b Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Sun, 14 Apr 2024 11:35:01 +0200 Subject: [PATCH 01/33] Run filecheck on dest-prop/branch.rs --- tests/mir-opt/dest-prop/branch.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dest-prop/branch.rs b/tests/mir-opt/dest-prop/branch.rs index cd55130728570..b1741bb2395c3 100644 --- a/tests/mir-opt/dest-prop/branch.rs +++ b/tests/mir-opt/dest-prop/branch.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //! Tests that assignment in both branches of an `if` are eliminated. //@ unit-test: DestinationPropagation @@ -12,6 +11,10 @@ fn cond() -> bool { // EMIT_MIR branch.foo.DestinationPropagation.diff fn foo() -> i32 { + // CHECK-LABEL: fn foo( + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[y]] = val() + // CHECK-NOT: [[y]] = {{_.*}}; let x = val(); let y = if cond() { From f238eba6211635d80ff0c31e7a89e2d38e528cfc Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Sun, 14 Apr 2024 11:35:23 +0200 Subject: [PATCH 02/33] Run filecheck on dest-prop/copy_propagation.rs --- .../mir-opt/dest-prop/copy_propagation_arg.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs index f84b5fde8d88b..2ea5c098ff40a 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.rs +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // Check that DestinationPropagation does not propagate an assignment to a function argument // (doing so can break usages of the original argument value) @@ -9,18 +8,29 @@ fn dummy(x: u8) -> u8 { // EMIT_MIR copy_propagation_arg.foo.DestinationPropagation.diff fn foo(mut x: u8) { + // CHECK-LABEL: fn foo( + // CHECK: debug x => [[x:_.*]]; + // CHECK: dummy(move [[x]]) + // CHECK: [[x]] = move {{_.*}}; // calling `dummy` to make a use of `x` that copyprop cannot eliminate x = dummy(x); // this will assign a local to `x` } // EMIT_MIR copy_propagation_arg.bar.DestinationPropagation.diff fn bar(mut x: u8) { + // CHECK-LABEL: fn bar( + // CHECK: debug x => [[x:_.*]]; + // CHECK: dummy(move [[x]]) + // CHECK: [[x]] = const 5_u8; dummy(x); x = 5; } // EMIT_MIR copy_propagation_arg.baz.DestinationPropagation.diff fn baz(mut x: i32) -> i32 { + // CHECK-LABEL: fn baz( + // CHECK: debug x => [[x:_.*]]; + // CHECK-NOT: [[x]] = {{_.*}} // self-assignment to a function argument should be eliminated x = x; x @@ -28,6 +38,12 @@ fn baz(mut x: i32) -> i32 { // EMIT_MIR copy_propagation_arg.arg_src.DestinationPropagation.diff fn arg_src(mut x: i32) -> i32 { + // CHECK-LABEL: fn arg_src( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[y]] = [[x]] + // CHECK: [[x]] = const 123_i32; + // CHECK-NOT: {{_.*}} = [[y]]; let y = x; x = 123; // Don't propagate this assignment to `y` y From 853311c35811ea8a05baf97aae895b017b83cc23 Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Sun, 14 Apr 2024 11:35:37 +0200 Subject: [PATCH 03/33] Run filecheck on dest-prop/cycle.rs --- tests/mir-opt/dest-prop/cycle.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dest-prop/cycle.rs b/tests/mir-opt/dest-prop/cycle.rs index e6663956d7822..41d9dd81253fe 100644 --- a/tests/mir-opt/dest-prop/cycle.rs +++ b/tests/mir-opt/dest-prop/cycle.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code. //@ unit-test: DestinationPropagation @@ -8,6 +7,10 @@ fn val() -> i32 { // EMIT_MIR cycle.main.DestinationPropagation.diff fn main() { + // CHECK-LABEL: main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[x]] = val() + // CHECK-NOT: [[x]] = {{_.*}}; let mut x = val(); let y = x; let z = y; From 069209034dfdaf520dc14aa4f0bfab935da0032c Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Sun, 14 Apr 2024 11:35:55 +0200 Subject: [PATCH 04/33] Run filecheck on dest-prop/dead_stores_79191.rs and dead_stores_better.rs --- tests/mir-opt/dest-prop/dead_stores_79191.rs | 8 +++++++- tests/mir-opt/dest-prop/dead_stores_better.rs | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.rs b/tests/mir-opt/dest-prop/dead_stores_79191.rs index b3e370966d05d..85411b17569da 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.rs +++ b/tests/mir-opt/dest-prop/dead_stores_79191.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ unit-test: DestinationPropagation @@ -8,6 +7,13 @@ fn id(x: T) -> T { // EMIT_MIR dead_stores_79191.f.DestinationPropagation.after.mir fn f(mut a: usize) -> usize { + // CHECK-LABEL: fn f( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: [[b]] = [[a]]; + // CHECK: [[a]] = const 5_usize; + // CHECK: [[a]] = move [[b]]; + // CHECK: id::(move [[a]]) let b = a; a = 5; a = b; diff --git a/tests/mir-opt/dest-prop/dead_stores_better.rs b/tests/mir-opt/dest-prop/dead_stores_better.rs index c241d71594bab..3d2af421bc237 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.rs +++ b/tests/mir-opt/dest-prop/dead_stores_better.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates // that that pass enables this one to do more optimizations. @@ -12,6 +11,13 @@ fn id(x: T) -> T { // EMIT_MIR dead_stores_better.f.DestinationPropagation.after.mir pub fn f(mut a: usize) -> usize { + // CHECK-LABEL: fn f( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: [[b]] = [[a]]; + // CHECK: [[a]] = const 5_usize; + // CHECK: [[a]] = move [[b]]; + // CHECK: id::(move [[a]]) let b = a; a = 5; a = b; From f0f867e2d3d220ae8a11bfe83d2545ec1a3a19d2 Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Sun, 14 Apr 2024 11:36:24 +0200 Subject: [PATCH 05/33] Run filecheck on dest-prop/simple.rs --- tests/mir-opt/dest-prop/simple.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs index 4aa6b6a4876e4..203f44a38261d 100644 --- a/tests/mir-opt/dest-prop/simple.rs +++ b/tests/mir-opt/dest-prop/simple.rs @@ -1,9 +1,12 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too. //@ unit-test: DestinationPropagation // EMIT_MIR simple.nrvo.DestinationPropagation.diff fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { + // CHECK-LABEL: fn nrvo( + // CHECK: debug init => [[init:_.*]]; + // CHECK-NOT: {{_.*}} = [[init]]; + // CHECK: move [[init]](move {{_.*}}) let mut buf = [0; 1024]; init(&mut buf); buf From 2d5a4832f30d246b81c775aa5bf9003997568b65 Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Wed, 26 Jun 2024 19:39:37 +0200 Subject: [PATCH 06/33] Acknowledge comments --- tests/mir-opt/dest-prop/copy_propagation_arg.rs | 2 +- tests/mir-opt/dest-prop/simple.rs | 3 +++ tests/mir-opt/dest-prop/union.rs | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs index 2ea5c098ff40a..5d99920ebc467 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.rs +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs @@ -30,7 +30,7 @@ fn bar(mut x: u8) { fn baz(mut x: i32) -> i32 { // CHECK-LABEL: fn baz( // CHECK: debug x => [[x:_.*]]; - // CHECK-NOT: [[x]] = {{_.*}} + // CHECK-NOT: [[x]] = // self-assignment to a function argument should be eliminated x = x; x diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs index 203f44a38261d..a2c0e976b5fc2 100644 --- a/tests/mir-opt/dest-prop/simple.rs +++ b/tests/mir-opt/dest-prop/simple.rs @@ -5,8 +5,11 @@ fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { // CHECK-LABEL: fn nrvo( // CHECK: debug init => [[init:_.*]]; + // CHECK: debug buf => [[buf:_.*]]; + // CHECK: [[buf]] = [const 0_u8; 1024]; // CHECK-NOT: {{_.*}} = [[init]]; // CHECK: move [[init]](move {{_.*}}) + // CHECK: {{_.*}} = [[buf]] let mut buf = [0; 1024]; init(&mut buf); buf diff --git a/tests/mir-opt/dest-prop/union.rs b/tests/mir-opt/dest-prop/union.rs index abd1f1b2c937a..54c284e5b5529 100644 --- a/tests/mir-opt/dest-prop/union.rs +++ b/tests/mir-opt/dest-prop/union.rs @@ -8,6 +8,8 @@ fn val() -> u32 { // EMIT_MIR union.main.DestinationPropagation.diff fn main() { + // CHECK-LABEL: fn args( + // CHECK: {{_.*}} = Un { us: const 1_u32 }; union Un { us: u32, } From 04eed9bc2412b2a5e90bf6924e71c5113f58901e Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 30 Jun 2024 18:23:07 +1000 Subject: [PATCH 07/33] Initial implementation of annoymous_pipe Signed-off-by: Jiahao XU --- library/std/src/io/mod.rs | 2 + library/std/src/io/pipe/mod.rs | 238 ++++++++++++++++++++++ library/std/src/sys/pal/unix/pipe.rs | 5 + library/std/src/sys/pal/windows/handle.rs | 1 + library/std/src/sys/pal/windows/pipe.rs | 6 +- 5 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 library/std/src/io/pipe/mod.rs diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 97b72f9664bb9..1e8ed2bb5bf13 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -338,6 +338,8 @@ pub(crate) mod copy; mod cursor; mod error; mod impls; +#[unstable(feature = "annoymous_pipe", issue = "")] +pub mod pipe; pub mod prelude; mod stdio; mod util; diff --git a/library/std/src/io/pipe/mod.rs b/library/std/src/io/pipe/mod.rs new file mode 100644 index 0000000000000..1919707a31fda --- /dev/null +++ b/library/std/src/io/pipe/mod.rs @@ -0,0 +1,238 @@ +use crate::{io, process::Stdio, sys::pipe::AnonPipe}; + +/// Create annoymous pipe that is close-on-exec and blocking. +#[inline] +pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { + cfg_if::cfg_if! { + if #[cfg(unix)] { + unix::pipe() + } else { + windows::pipe() + } + } +} + +#[derive(Debug)] +pub struct PipeReader(AnonPipe); + +#[derive(Debug)] +pub struct PipeWriter(AnonPipe); + +pub struct NotAPipeError; + +impl PipeReader { + /// Create a new [`PipeReader`] instance that shares the same underlying file description. + pub fn try_clone(&self) -> io::Result { + self.0.try_clone().map(Self) + } +} + +impl PipeWriter { + /// Create a new [`PipeWriter`] instance that shares the same underlying file description. + pub fn try_clone(&self) -> io::Result { + self.0.try_clone().map(Self) + } +} + +macro_rules! forward_io_read_traits { + ($name:ty) => { + impl io::Read for $name { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.0.read_to_end(buf) + } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + } + }; +} +forward_io_read_traits!(PipeReader); +forward_io_read_traits!(&PipeReader); + +macro_rules! forward_io_write_traits { + ($name:ty) => { + impl io::Write for $name { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } + } + }; +} +forward_io_write_traits!(PipeWriter); +forward_io_write_traits!(&PipeWriter); + +#[cfg(unix)] +mod unix { + use super::*; + + use crate::{ + os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, + sys::{ + fd::FileDesc, + pipe::{anon_pipe, AnonPipe}, + }, + sys_common::{FromInner, IntoInner}, + }; + + #[inline] + pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { + anon_pipe().map(|(rx, tx)| (PipeReader(rx), PipeWriter(tx))) + } + + macro_rules! impl_traits { + ($name:ty) => { + impl AsFd for $name { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } + } + impl AsRawFd for $name { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } + } + impl From<$name> for OwnedFd { + fn from(pipe: $name) -> Self { + FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) + } + } + impl FromRawFd for $name { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self(AnonPipe::from_raw_fd(raw_fd)) + } + } + impl IntoRawFd for $name { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } + } + impl From<$name> for Stdio { + fn from(pipe: $name) -> Self { + Self::from(OwnedFd::from(pipe)) + } + } + }; + } + impl_traits!(PipeReader); + impl_traits!(PipeWriter); + + fn owned_fd_to_anon_pipe(owned_fd: OwnedFd) -> AnonPipe { + AnonPipe::from_inner(FileDesc::from_inner(owned_fd)) + } + + impl TryFrom for PipeReader { + type Error = NotAPipeError; + + fn try_from(owned_fd: OwnedFd) -> Result { + Ok(Self(owned_fd_to_anon_pipe(owned_fd))) + } + } + + impl TryFrom for PipeWriter { + type Error = NotAPipeError; + + fn try_from(owned_fd: OwnedFd) -> Result { + Ok(Self(owned_fd_to_anon_pipe(owned_fd))) + } + } +} + +#[cfg(windows)] +mod windows { + use super::*; + + use crate::{ + os::windows::io::{ + AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, + RawHandle, + }, + sys::{ + handle::Handle, + pipe::{anon_pipe, AnonPipe, Pipes}, + }, + sys_common::{FromInner, IntoInner}, + }; + + #[inline] + pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { + anon_pipe(true, false).map(|Pipes { ours, their }| (PipeReader(ours), PipeWrite(theirs))) + } + + macro_rules! impl_traits { + ($name:ty) => { + impl AsHandle for $name { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.handle().as_handle() + } + } + impl AsRawHandle for $name { + fn as_raw_handle(&self) -> RawHandle { + self.0.handle().as_raw_handle() + } + } + + impl FromRawHandle for $name { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) + } + } + impl IntoRawHandle for $name { + fn into_raw_handle(self) -> RawHandle { + self.0.into_handle().into_raw_handle() + } + } + + impl From<$name> for OwnedHandle { + fn from(pipe: $name) -> Self { + Handle::into_inner(AnonPipe::into_inner(pipe.0)) + } + } + impl From<$name> for Stdio { + fn from(pipe: $name) -> Self { + Self::from(OwnedHandle::from(pipe)) + } + } + }; + } + impl_traits!(PipeReader); + impl_traits!(PipeWriter); + + fn owned_handle_to_anon_pipe(owned_handle: OwnedHandle) -> AnonPipe { + AnonPipe::from_inner(Handle::from_inner(owned_handle)) + } + + impl TryFrom for PipeReader { + type Error = NotAPipeError; + + fn try_from(owned_handle: OwnedHandle) -> Result { + Ok(Self(owned_handle_to_anon_pipe(owned_handle))) + } + } + + impl TryFrom for PipeWriter { + type Error = NotAPipeError; + + fn try_from(owned_handle: OwnedHandle) -> Result { + Ok(Self(owned_handle_to_anon_pipe(owned_handle))) + } + } +} diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 33db24e77e4da..c2fb9c449cf08 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -9,6 +9,7 @@ use crate::sys_common::{FromInner, IntoInner}; // Anonymous pipes //////////////////////////////////////////////////////////////////////////////// +#[derive(Debug)] pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { @@ -46,6 +47,10 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { } impl AnonPipe { + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(Self) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } diff --git a/library/std/src/sys/pal/windows/handle.rs b/library/std/src/sys/pal/windows/handle.rs index 3f85bb0a099a9..5aa2141571953 100644 --- a/library/std/src/sys/pal/windows/handle.rs +++ b/library/std/src/sys/pal/windows/handle.rs @@ -17,6 +17,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// An owned container for `HANDLE` object, closing them on Drop. /// /// All methods are inherited through a `Deref` impl to `RawHandle` +#[derive(Debug)] pub struct Handle(OwnedHandle); impl Handle { diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index 67ef3ca82da02..6e6ba721d00fa 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -19,6 +19,7 @@ use crate::sys_common::{FromInner, IntoInner}; // Anonymous pipes //////////////////////////////////////////////////////////////////////////////// +#[derive(Debug)] pub struct AnonPipe { inner: Handle, } @@ -182,7 +183,7 @@ pub fn spawn_pipe_relay( their_handle_inheritable: bool, ) -> io::Result { // We need this handle to live for the lifetime of the thread spawned below. - let source = source.duplicate()?; + let source = source.try_clone()?; // create a new pair of anon pipes. let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?; @@ -238,7 +239,8 @@ impl AnonPipe { pub fn into_handle(self) -> Handle { self.inner } - fn duplicate(&self) -> io::Result { + + pub fn try_clone(&self) -> io::Result { self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner }) } From 72bda33a5b94a57b6fc262657899fd90a61931a7 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 30 Jun 2024 18:35:38 +1000 Subject: [PATCH 08/33] Fix compilation errors Signed-off-by: Jiahao XU --- library/std/src/io/mod.rs | 3 ++- library/std/src/io/pipe/mod.rs | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 1e8ed2bb5bf13..0e95ae8151c90 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -338,7 +338,8 @@ pub(crate) mod copy; mod cursor; mod error; mod impls; -#[unstable(feature = "annoymous_pipe", issue = "")] +/// Annoymous pipe implementation +#[unstable(feature = "annoymous_pipe", issue = "127154")] pub mod pipe; pub mod prelude; mod stdio; diff --git a/library/std/src/io/pipe/mod.rs b/library/std/src/io/pipe/mod.rs index 1919707a31fda..b5fa4b0bfc90d 100644 --- a/library/std/src/io/pipe/mod.rs +++ b/library/std/src/io/pipe/mod.rs @@ -12,12 +12,16 @@ pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { } } +/// Read end of the annoymous pipe. #[derive(Debug)] pub struct PipeReader(AnonPipe); +/// Write end of the annoymous pipe. #[derive(Debug)] pub struct PipeWriter(AnonPipe); +/// The owned fd provided is not a pipe. +#[derive(Debug)] pub struct NotAPipeError; impl PipeReader { @@ -174,7 +178,7 @@ mod windows { #[inline] pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { - anon_pipe(true, false).map(|Pipes { ours, their }| (PipeReader(ours), PipeWrite(theirs))) + anon_pipe(true, false).map(|Pipes { ours, theirs }| (PipeReader(ours), PipeWriter(theirs))) } macro_rules! impl_traits { From 42e8beb64cac0124491fb86e2c42ee32d0f6c0f5 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 30 Jun 2024 19:19:11 +1000 Subject: [PATCH 09/33] Implement validation in `TryFrom for PIpe*` on unix Signed-off-by: Jiahao XU --- library/std/src/io/pipe/mod.rs | 64 +++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/library/std/src/io/pipe/mod.rs b/library/std/src/io/pipe/mod.rs index b5fa4b0bfc90d..7f07126e412f4 100644 --- a/library/std/src/io/pipe/mod.rs +++ b/library/std/src/io/pipe/mod.rs @@ -20,10 +20,6 @@ pub struct PipeReader(AnonPipe); #[derive(Debug)] pub struct PipeWriter(AnonPipe); -/// The owned fd provided is not a pipe. -#[derive(Debug)] -pub struct NotAPipeError; - impl PipeReader { /// Create a new [`PipeReader`] instance that shares the same underlying file description. pub fn try_clone(&self) -> io::Result { @@ -89,7 +85,11 @@ mod unix { use super::*; use crate::{ - os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, + fs::File, + os::{ + fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, + unix::fs::FileTypeExt, + }, sys::{ fd::FileDesc, pipe::{anon_pipe, AnonPipe}, @@ -139,23 +139,61 @@ mod unix { impl_traits!(PipeReader); impl_traits!(PipeWriter); - fn owned_fd_to_anon_pipe(owned_fd: OwnedFd) -> AnonPipe { - AnonPipe::from_inner(FileDesc::from_inner(owned_fd)) + fn convert_to_pipe(owned_fd: OwnedFd) -> io::Result { + let file = File::from(owned_fd); + if file.metadata()?.file_type().is_fifo() { + Ok(AnonPipe::from_inner(FileDesc::from_inner(OwnedFd::from(file)))) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) + } + } + + enum AccessMode { + Readable, + Writable, + } + + fn check_access_mode(pipe: AnonPipe, expected_access_mode: AccessMode) -> io::Result { + let ret = unsafe { libc::fcntl(pipe.as_raw_fd(), libc::F_GETFL) }; + let access_mode = ret & libc::O_ACCMODE; + let expected_access_mode_str = match expected_access_mode { + AccessMode::Readable => "readable", + AccessMode::Writable => "writable", + }; + let expected_access_mode = match expected_access_mode { + AccessMode::Readable => libc::O_RDONLY, + AccessMode::Writable => libc::O_WRONLY, + }; + + if ret == -1 { + Err(io::Error::last_os_error()) + } else if access_mode == libc::O_RDWR && access_mode == expected_access_mode { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("Pipe {} is not {}", pipe.as_raw_fd(), expected_access_mode_str), + )) + } else { + Ok(pipe) + } } impl TryFrom for PipeReader { - type Error = NotAPipeError; + type Error = io::Error; fn try_from(owned_fd: OwnedFd) -> Result { - Ok(Self(owned_fd_to_anon_pipe(owned_fd))) + convert_to_pipe(owned_fd) + .and_then(|pipe| check_access_mode(pipe, AccessMode::Readable)) + .map(Self) } } impl TryFrom for PipeWriter { - type Error = NotAPipeError; + type Error = io::Error; fn try_from(owned_fd: OwnedFd) -> Result { - Ok(Self(owned_fd_to_anon_pipe(owned_fd))) + convert_to_pipe(owned_fd) + .and_then(|pipe| check_access_mode(pipe, AccessMode::Writable)) + .map(Self) } } } @@ -225,7 +263,7 @@ mod windows { } impl TryFrom for PipeReader { - type Error = NotAPipeError; + type Error = io::Error; fn try_from(owned_handle: OwnedHandle) -> Result { Ok(Self(owned_handle_to_anon_pipe(owned_handle))) @@ -233,7 +271,7 @@ mod windows { } impl TryFrom for PipeWriter { - type Error = NotAPipeError; + type Error = io::Error; fn try_from(owned_handle: OwnedHandle) -> Result { Ok(Self(owned_handle_to_anon_pipe(owned_handle))) From e170c7841613163383b323e88e282a3aeccaebb0 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 30 Jun 2024 19:21:48 +1000 Subject: [PATCH 10/33] Move the mod `pipe` to `std::net` Signed-off-by: Jiahao XU --- library/std/src/io/mod.rs | 3 --- library/std/src/net/mod.rs | 4 ++++ library/std/src/{io => net}/pipe/mod.rs | 0 3 files changed, 4 insertions(+), 3 deletions(-) rename library/std/src/{io => net}/pipe/mod.rs (100%) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 0e95ae8151c90..97b72f9664bb9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -338,9 +338,6 @@ pub(crate) mod copy; mod cursor; mod error; mod impls; -/// Annoymous pipe implementation -#[unstable(feature = "annoymous_pipe", issue = "127154")] -pub mod pipe; pub mod prelude; mod stdio; mod util; diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index 858776f14466a..7e9a89916cf09 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -43,6 +43,10 @@ mod tcp; pub(crate) mod test; mod udp; +/// Annoymous pipe implementation +#[unstable(feature = "annoymous_pipe", issue = "127154")] +pub mod pipe; + /// Possible values which can be passed to the [`TcpStream::shutdown`] method. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/pipe/mod.rs b/library/std/src/net/pipe/mod.rs similarity index 100% rename from library/std/src/io/pipe/mod.rs rename to library/std/src/net/pipe/mod.rs From 473fbce50c970175e14c37b72e9b925c440c65a8 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 30 Jun 2024 23:05:33 +1000 Subject: [PATCH 11/33] Fix typo Signed-off-by: Jiahao XU --- library/std/src/net/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index 7e9a89916cf09..1fef8fc604cd0 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -43,8 +43,8 @@ mod tcp; pub(crate) mod test; mod udp; -/// Annoymous pipe implementation -#[unstable(feature = "annoymous_pipe", issue = "127154")] +/// Anonymous pipe implementation +#[unstable(feature = "anonymous_pipe", issue = "127154")] pub mod pipe; /// Possible values which can be passed to the [`TcpStream::shutdown`] method. From 97626b6ee3eb53b206d36900dc1d017744951963 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 30 Jun 2024 23:47:57 +1000 Subject: [PATCH 12/33] Fix tidy errors Signed-off-by: Jiahao XU --- library/std/src/net/mod.rs | 6 ++--- .../pipe/mod.rs => sys/anonymous_pipe.rs} | 23 +++++++++++++++++++ library/std/src/sys/mod.rs | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) rename library/std/src/{net/pipe/mod.rs => sys/anonymous_pipe.rs} (84%) diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index 1fef8fc604cd0..cacf8c01f672d 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -33,6 +33,8 @@ pub use self::tcp::IntoIncoming; pub use self::tcp::{Incoming, TcpListener, TcpStream}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::udp::UdpSocket; +#[unstable(feature = "anonymous_pipe", issue = "127154")] +pub use crate::sys::anonymous_pipe::{pipe, PipeReader, PipeWriter}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::net::AddrParseError; @@ -43,10 +45,6 @@ mod tcp; pub(crate) mod test; mod udp; -/// Anonymous pipe implementation -#[unstable(feature = "anonymous_pipe", issue = "127154")] -pub mod pipe; - /// Possible values which can be passed to the [`TcpStream::shutdown`] method. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/net/pipe/mod.rs b/library/std/src/sys/anonymous_pipe.rs similarity index 84% rename from library/std/src/net/pipe/mod.rs rename to library/std/src/sys/anonymous_pipe.rs index 7f07126e412f4..aa7cad2a7de19 100644 --- a/library/std/src/net/pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe.rs @@ -1,6 +1,7 @@ use crate::{io, process::Stdio, sys::pipe::AnonPipe}; /// Create annoymous pipe that is close-on-exec and blocking. +#[unstable(feature = "anonymous_pipe", issue = "127154")] #[inline] pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { cfg_if::cfg_if! { @@ -13,15 +14,18 @@ pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { } /// Read end of the annoymous pipe. +#[unstable(feature = "anonymous_pipe", issue = "127154")] #[derive(Debug)] pub struct PipeReader(AnonPipe); /// Write end of the annoymous pipe. +#[unstable(feature = "anonymous_pipe", issue = "127154")] #[derive(Debug)] pub struct PipeWriter(AnonPipe); impl PipeReader { /// Create a new [`PipeReader`] instance that shares the same underlying file description. + #[unstable(feature = "anonymous_pipe", issue = "127154")] pub fn try_clone(&self) -> io::Result { self.0.try_clone().map(Self) } @@ -29,6 +33,7 @@ impl PipeReader { impl PipeWriter { /// Create a new [`PipeWriter`] instance that shares the same underlying file description. + #[unstable(feature = "anonymous_pipe", issue = "127154")] pub fn try_clone(&self) -> io::Result { self.0.try_clone().map(Self) } @@ -36,6 +41,7 @@ impl PipeWriter { macro_rules! forward_io_read_traits { ($name:ty) => { + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl io::Read for $name { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -60,6 +66,7 @@ forward_io_read_traits!(&PipeReader); macro_rules! forward_io_write_traits { ($name:ty) => { + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl io::Write for $name { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -104,31 +111,37 @@ mod unix { macro_rules! impl_traits { ($name:ty) => { + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl AsFd for $name { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl AsRawFd for $name { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl From<$name> for OwnedFd { fn from(pipe: $name) -> Self { FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl FromRawFd for $name { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { Self(AnonPipe::from_raw_fd(raw_fd)) } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl IntoRawFd for $name { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl From<$name> for Stdio { fn from(pipe: $name) -> Self { Self::from(OwnedFd::from(pipe)) @@ -177,6 +190,7 @@ mod unix { } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl TryFrom for PipeReader { type Error = io::Error; @@ -187,6 +201,7 @@ mod unix { } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl TryFrom for PipeWriter { type Error = io::Error; @@ -221,33 +236,39 @@ mod windows { macro_rules! impl_traits { ($name:ty) => { + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl AsHandle for $name { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.handle().as_handle() } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl AsRawHandle for $name { fn as_raw_handle(&self) -> RawHandle { self.0.handle().as_raw_handle() } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl FromRawHandle for $name { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl IntoRawHandle for $name { fn into_raw_handle(self) -> RawHandle { self.0.into_handle().into_raw_handle() } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl From<$name> for OwnedHandle { fn from(pipe: $name) -> Self { Handle::into_inner(AnonPipe::into_inner(pipe.0)) } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl From<$name> for Stdio { fn from(pipe: $name) -> Self { Self::from(OwnedHandle::from(pipe)) @@ -262,6 +283,7 @@ mod windows { AnonPipe::from_inner(Handle::from_inner(owned_handle)) } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl TryFrom for PipeReader { type Error = io::Error; @@ -270,6 +292,7 @@ mod windows { } } + #[unstable(feature = "anonymous_pipe", issue = "127154")] impl TryFrom for PipeWriter { type Error = io::Error; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 8aa35c40fe052..fad01f581577d 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -5,6 +5,7 @@ mod pal; mod personality; +pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; pub mod os_str; From d60438fa2207490fdbe50d13b61db3b9af9befa4 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 1 Jul 2024 00:37:26 +1000 Subject: [PATCH 13/33] Validate pipe in `TryFrom for Pipe*` Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe.rs b/library/std/src/sys/anonymous_pipe.rs index aa7cad2a7de19..230f56c2001e8 100644 --- a/library/std/src/sys/anonymous_pipe.rs +++ b/library/std/src/sys/anonymous_pipe.rs @@ -223,6 +223,7 @@ mod windows { RawHandle, }, sys::{ + c::{GetFileType, FILE_TYPE_PIPE}, handle::Handle, pipe::{anon_pipe, AnonPipe, Pipes}, }, @@ -279,8 +280,12 @@ mod windows { impl_traits!(PipeReader); impl_traits!(PipeWriter); - fn owned_handle_to_anon_pipe(owned_handle: OwnedHandle) -> AnonPipe { - AnonPipe::from_inner(Handle::from_inner(owned_handle)) + fn convert_to_pipe(owned_handle: OwnedHandle) -> io::Result { + if unsafe { GetFileType(owned_handle.as_raw_handle()) } == FILE_TYPE_PIPE { + Ok(AnonPipe::from_inner(Handle::from_inner(owned_handle))) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) + } } #[unstable(feature = "anonymous_pipe", issue = "127154")] @@ -288,7 +293,7 @@ mod windows { type Error = io::Error; fn try_from(owned_handle: OwnedHandle) -> Result { - Ok(Self(owned_handle_to_anon_pipe(owned_handle))) + convert_to_pipe(owned_handle).map(Self) } } @@ -297,7 +302,7 @@ mod windows { type Error = io::Error; fn try_from(owned_handle: OwnedHandle) -> Result { - Ok(Self(owned_handle_to_anon_pipe(owned_handle))) + convert_to_pipe(owned_handle).map(Self) } } } From b7af685cc2c50371cc687704a566a665f09ea215 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 1 Jul 2024 00:51:00 +1000 Subject: [PATCH 14/33] Refactor: Extract new method `FileDesc::get_access_mode` ALso fixed a bug in the original implementation Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe.rs | 51 +++++++++++---------------- library/std/src/sys/pal/unix/fd.rs | 34 ++++++++++++------ library/std/src/sys/pal/unix/pipe.rs | 4 +++ 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe.rs b/library/std/src/sys/anonymous_pipe.rs index 230f56c2001e8..1481fcf30e4b9 100644 --- a/library/std/src/sys/anonymous_pipe.rs +++ b/library/std/src/sys/anonymous_pipe.rs @@ -161,42 +161,22 @@ mod unix { } } - enum AccessMode { - Readable, - Writable, - } - - fn check_access_mode(pipe: AnonPipe, expected_access_mode: AccessMode) -> io::Result { - let ret = unsafe { libc::fcntl(pipe.as_raw_fd(), libc::F_GETFL) }; - let access_mode = ret & libc::O_ACCMODE; - let expected_access_mode_str = match expected_access_mode { - AccessMode::Readable => "readable", - AccessMode::Writable => "writable", - }; - let expected_access_mode = match expected_access_mode { - AccessMode::Readable => libc::O_RDONLY, - AccessMode::Writable => libc::O_WRONLY, - }; - - if ret == -1 { - Err(io::Error::last_os_error()) - } else if access_mode == libc::O_RDWR && access_mode == expected_access_mode { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("Pipe {} is not {}", pipe.as_raw_fd(), expected_access_mode_str), - )) - } else { - Ok(pipe) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] impl TryFrom for PipeReader { type Error = io::Error; fn try_from(owned_fd: OwnedFd) -> Result { convert_to_pipe(owned_fd) - .and_then(|pipe| check_access_mode(pipe, AccessMode::Readable)) + .and_then(|pipe| { + if pipe.as_file_desc().get_access_mode()?.readable { + Ok(pipe) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("Pipe {} is not readable", pipe.as_raw_fd()), + )) + } + }) .map(Self) } } @@ -207,7 +187,16 @@ mod unix { fn try_from(owned_fd: OwnedFd) -> Result { convert_to_pipe(owned_fd) - .and_then(|pipe| check_access_mode(pipe, AccessMode::Writable)) + .and_then(|pipe| { + if pipe.as_file_desc().get_access_mode()?.writable { + Ok(pipe) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("Pipe {} is not writable", pipe.as_raw_fd()), + )) + } + }) .map(Self) } } diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index 1701717db597c..d889a95f891a7 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -26,6 +26,11 @@ use libc::off64_t; )))] use libc::off_t as off64_t; +pub struct AccessMode { + pub readable: bool, + pub writable: bool, +} + #[derive(Debug)] pub struct FileDesc(OwnedFd); @@ -518,20 +523,27 @@ impl FileDesc { } } + fn get_flags(&self) -> io::Result { + unsafe { cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL)) } + } + + pub fn get_access_mode(&self) -> io::Result { + let access_mode = self.get_flags()? & libc::O_ACCMODE; + Ok(AccessMode { + readable: access_mode == libc::O_RDWR || access_mode == libc::O_RDONLY, + writable: access_mode == libc::O_RDWR || access_mode == libc::O_WRONLY, + }) + } + #[cfg(not(target_os = "linux"))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - unsafe { - let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL))?; - let new = if nonblocking { - previous | libc::O_NONBLOCK - } else { - previous & !libc::O_NONBLOCK - }; - if new != previous { - cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new))?; - } - Ok(()) + let previous = self.get_flags()?; + let new = + if nonblocking { previous | libc::O_NONBLOCK } else { previous & !libc::O_NONBLOCK }; + if new != previous { + unsafe { cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new)) }?; } + Ok(()) } #[inline] diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index c2fb9c449cf08..8762af614f17e 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -84,6 +84,10 @@ impl AnonPipe { pub fn is_write_vectored(&self) -> bool { self.0.is_write_vectored() } + + pub fn as_file_desc(&self) -> &FileDesc { + &self.0 + } } impl IntoInner for AnonPipe { From 4c6b6bbb850627ab22f2866b750770bd4e90a183 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 2 Jul 2024 00:15:31 +1000 Subject: [PATCH 15/33] Add testing for anonymous pipe Signed-off-by: Jiahao XU --- .../mod.rs} | 3 + library/std/src/sys/anonymous_pipe/tests.rs | 128 ++++++++++++++++++ 2 files changed, 131 insertions(+) rename library/std/src/sys/{anonymous_pipe.rs => anonymous_pipe/mod.rs} (99%) create mode 100644 library/std/src/sys/anonymous_pipe/tests.rs diff --git a/library/std/src/sys/anonymous_pipe.rs b/library/std/src/sys/anonymous_pipe/mod.rs similarity index 99% rename from library/std/src/sys/anonymous_pipe.rs rename to library/std/src/sys/anonymous_pipe/mod.rs index 1481fcf30e4b9..9f2483ad290c2 100644 --- a/library/std/src/sys/anonymous_pipe.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -295,3 +295,6 @@ mod windows { } } } + +#[cfg(test)] +mod tests; diff --git a/library/std/src/sys/anonymous_pipe/tests.rs b/library/std/src/sys/anonymous_pipe/tests.rs new file mode 100644 index 0000000000000..048e011fc5eaf --- /dev/null +++ b/library/std/src/sys/anonymous_pipe/tests.rs @@ -0,0 +1,128 @@ +use super::*; +use crate::io::{Read, Write}; + +#[test] +fn pipe_creation_and_rw() { + let (mut rx, mut tx) = pipe().unwrap(); + tx.write_all(b"12345").unwrap(); + drop(tx); + + let mut s = String::new(); + rx.read_to_string(&mut s).unwrap(); + assert_eq!(s, "12345"); +} + +#[test] +fn pipe_try_clone_and_rw() { + let (mut rx, mut tx) = pipe().unwrap(); + tx.try_clone().unwrap().write_all(b"12").unwrap(); + tx.write_all(b"345").unwrap(); + drop(tx); + + let mut s = String::new(); + rx.try_clone().unwrap().take(3).read_to_string(&mut s).unwrap(); + assert_eq!(s, "123"); + + s.clear(); + rx.read_to_string(&mut s).unwrap(); + assert_eq!(s, "45"); +} + +#[cfg(unix)] +mod unix_specific { + use super::*; + + use crate::{ + fs::File, + io, + os::fd::{AsRawFd, OwnedFd}, + }; + + #[test] + fn pipe_owned_fd_round_trip_conversion() { + let (rx, tx) = pipe().unwrap(); + let raw_fds = (rx.as_raw_fd(), tx.as_raw_fd()); + let (rx_owned_fd, tx_owned_fd) = (OwnedFd::from(rx), OwnedFd::from(tx)); + + let rx = PipeReader::try_from(rx_owned_fd).unwrap(); + let tx = PipeWriter::try_from(tx_owned_fd).unwrap(); + assert_eq!(raw_fds, (rx.as_raw_fd(), tx.as_raw_fd())); + } + + #[test] + fn convert_from_non_pipe_to_pipe_reader_shall_fail() { + let file = File::open("/dev/zero").unwrap(); + let err = PipeReader::try_from(OwnedFd::from(file)).unwrap_err(); + + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); + } + + #[test] + fn convert_from_non_pipe_to_pipe_writer_shall_fail() { + let file = File::options().write(true).open("/dev/null").unwrap(); + let err = PipeWriter::try_from(OwnedFd::from(file)).unwrap_err(); + + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); + } + + #[test] + fn convert_pipe_writer_to_pipe_reader_shall_fail() { + let (_, tx) = pipe().unwrap(); + let fd = tx.as_raw_fd(); + let err = PipeReader::try_from(OwnedFd::from(tx)).unwrap_err(); + + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + assert_eq!(format!("{}", err.get_ref().unwrap()), format!("Pipe {fd} is not readable")); + } + + #[test] + fn convert_pipe_reader_to_pipe_writer_shall_fail() { + let (rx, _) = pipe().unwrap(); + let fd = rx.as_raw_fd(); + let err = PipeWriter::try_from(OwnedFd::from(rx)).unwrap_err(); + + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + assert_eq!(format!("{}", err.get_ref().unwrap()), format!("Pipe {fd} is not writable")); + } +} + +#[cfg(windows)] +mod windows_specific { + use super::*; + + use crate::{ + io, + os::windows::io::{AsHandle, AsRawHandle, OwnedHandle}, + }; + + #[test] + fn pipe_owned_handle_round_trip_conversion() { + let (rx, tx) = pipe().unwrap(); + let raw_handles = (rx.as_raw_handle(), tx.as_raw_handle()); + let (rx_owned_handle, tx_owned_handle) = (OwnedHandle::from(rx), OwnedHandle::from(tx)); + + let rx = PipeReader::try_from(rx_owned_handle).unwrap(); + let tx = PipeWriter::try_from(tx_owned_handle).unwrap(); + assert_eq!(raw_handles, (rx.as_raw_handle(), tx.as_raw_handle())); + } + + #[test] + fn convert_from_non_pipe_to_pipe_reader_shall_fail() { + let file = io::stdin().as_handle().try_clone_to_owned().unwrap(); + let err = PipeReader::try_from(OwnedHandle::from(file)).unwrap_err(); + + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); + } + + #[test] + fn convert_from_non_pipe_to_pipe_writer_shall_fail() { + let file = io::stdout().as_handle().try_clone_to_owned().unwrap(); + let err = PipeWriter::try_from(OwnedHandle::from(file)).unwrap_err(); + + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); + } +} From 594abecd54ba08b766b2410c53872165055c7d62 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 2 Jul 2024 19:14:56 +1000 Subject: [PATCH 16/33] Refactor: Put mod `unix` & `windows` into separate files Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/mod.rs | 207 +----------------- library/std/src/sys/anonymous_pipe/unix.rs | 111 ++++++++++ library/std/src/sys/anonymous_pipe/windows.rs | 89 ++++++++ 3 files changed, 202 insertions(+), 205 deletions(-) create mode 100644 library/std/src/sys/anonymous_pipe/unix.rs create mode 100644 library/std/src/sys/anonymous_pipe/windows.rs diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index 9f2483ad290c2..76c4a7c060224 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -88,213 +88,10 @@ forward_io_write_traits!(PipeWriter); forward_io_write_traits!(&PipeWriter); #[cfg(unix)] -mod unix { - use super::*; - - use crate::{ - fs::File, - os::{ - fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, - unix::fs::FileTypeExt, - }, - sys::{ - fd::FileDesc, - pipe::{anon_pipe, AnonPipe}, - }, - sys_common::{FromInner, IntoInner}, - }; - - #[inline] - pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { - anon_pipe().map(|(rx, tx)| (PipeReader(rx), PipeWriter(tx))) - } - - macro_rules! impl_traits { - ($name:ty) => { - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsFd for $name { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsRawFd for $name { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for OwnedFd { - fn from(pipe: $name) -> Self { - FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl FromRawFd for $name { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(AnonPipe::from_raw_fd(raw_fd)) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl IntoRawFd for $name { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for Stdio { - fn from(pipe: $name) -> Self { - Self::from(OwnedFd::from(pipe)) - } - } - }; - } - impl_traits!(PipeReader); - impl_traits!(PipeWriter); - - fn convert_to_pipe(owned_fd: OwnedFd) -> io::Result { - let file = File::from(owned_fd); - if file.metadata()?.file_type().is_fifo() { - Ok(AnonPipe::from_inner(FileDesc::from_inner(OwnedFd::from(file)))) - } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) - } - } - - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl TryFrom for PipeReader { - type Error = io::Error; - - fn try_from(owned_fd: OwnedFd) -> Result { - convert_to_pipe(owned_fd) - .and_then(|pipe| { - if pipe.as_file_desc().get_access_mode()?.readable { - Ok(pipe) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("Pipe {} is not readable", pipe.as_raw_fd()), - )) - } - }) - .map(Self) - } - } - - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl TryFrom for PipeWriter { - type Error = io::Error; - - fn try_from(owned_fd: OwnedFd) -> Result { - convert_to_pipe(owned_fd) - .and_then(|pipe| { - if pipe.as_file_desc().get_access_mode()?.writable { - Ok(pipe) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("Pipe {} is not writable", pipe.as_raw_fd()), - )) - } - }) - .map(Self) - } - } -} +mod unix; #[cfg(windows)] -mod windows { - use super::*; - - use crate::{ - os::windows::io::{ - AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, - RawHandle, - }, - sys::{ - c::{GetFileType, FILE_TYPE_PIPE}, - handle::Handle, - pipe::{anon_pipe, AnonPipe, Pipes}, - }, - sys_common::{FromInner, IntoInner}, - }; - - #[inline] - pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { - anon_pipe(true, false).map(|Pipes { ours, theirs }| (PipeReader(ours), PipeWriter(theirs))) - } - - macro_rules! impl_traits { - ($name:ty) => { - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsHandle for $name { - fn as_handle(&self) -> BorrowedHandle<'_> { - self.0.handle().as_handle() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsRawHandle for $name { - fn as_raw_handle(&self) -> RawHandle { - self.0.handle().as_raw_handle() - } - } - - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl FromRawHandle for $name { - unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl IntoRawHandle for $name { - fn into_raw_handle(self) -> RawHandle { - self.0.into_handle().into_raw_handle() - } - } - - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for OwnedHandle { - fn from(pipe: $name) -> Self { - Handle::into_inner(AnonPipe::into_inner(pipe.0)) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for Stdio { - fn from(pipe: $name) -> Self { - Self::from(OwnedHandle::from(pipe)) - } - } - }; - } - impl_traits!(PipeReader); - impl_traits!(PipeWriter); - - fn convert_to_pipe(owned_handle: OwnedHandle) -> io::Result { - if unsafe { GetFileType(owned_handle.as_raw_handle()) } == FILE_TYPE_PIPE { - Ok(AnonPipe::from_inner(Handle::from_inner(owned_handle))) - } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) - } - } - - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl TryFrom for PipeReader { - type Error = io::Error; - - fn try_from(owned_handle: OwnedHandle) -> Result { - convert_to_pipe(owned_handle).map(Self) - } - } - - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl TryFrom for PipeWriter { - type Error = io::Error; - - fn try_from(owned_handle: OwnedHandle) -> Result { - convert_to_pipe(owned_handle).map(Self) - } - } -} +mod windows; #[cfg(test)] mod tests; diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs new file mode 100644 index 0000000000000..0438d933a06c0 --- /dev/null +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -0,0 +1,111 @@ +use super::*; + +use crate::{ + fs::File, + os::{ + fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, + unix::fs::FileTypeExt, + }, + sys::{ + fd::FileDesc, + pipe::{anon_pipe, AnonPipe}, + }, + sys_common::{FromInner, IntoInner}, +}; + +#[inline] +pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { + anon_pipe().map(|(rx, tx)| (PipeReader(rx), PipeWriter(tx))) +} + +macro_rules! impl_traits { + ($name:ty) => { + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl AsFd for $name { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl AsRawFd for $name { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl From<$name> for OwnedFd { + fn from(pipe: $name) -> Self { + FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl FromRawFd for $name { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self(AnonPipe::from_raw_fd(raw_fd)) + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl IntoRawFd for $name { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl From<$name> for Stdio { + fn from(pipe: $name) -> Self { + Self::from(OwnedFd::from(pipe)) + } + } + }; +} +impl_traits!(PipeReader); +impl_traits!(PipeWriter); + +fn convert_to_pipe(owned_fd: OwnedFd) -> io::Result { + let file = File::from(owned_fd); + if file.metadata()?.file_type().is_fifo() { + Ok(AnonPipe::from_inner(FileDesc::from_inner(OwnedFd::from(file)))) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl TryFrom for PipeReader { + type Error = io::Error; + + fn try_from(owned_fd: OwnedFd) -> Result { + convert_to_pipe(owned_fd) + .and_then(|pipe| { + if pipe.as_file_desc().get_access_mode()?.readable { + Ok(pipe) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("Pipe {} is not readable", pipe.as_raw_fd()), + )) + } + }) + .map(Self) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl TryFrom for PipeWriter { + type Error = io::Error; + + fn try_from(owned_fd: OwnedFd) -> Result { + convert_to_pipe(owned_fd) + .and_then(|pipe| { + if pipe.as_file_desc().get_access_mode()?.writable { + Ok(pipe) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("Pipe {} is not writable", pipe.as_raw_fd()), + )) + } + }) + .map(Self) + } +} diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs new file mode 100644 index 0000000000000..cd132c5a60f41 --- /dev/null +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -0,0 +1,89 @@ +use super::*; + +use crate::{ + os::windows::io::{ + AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, + }, + sys::{ + c::{GetFileType, FILE_TYPE_PIPE}, + handle::Handle, + pipe::{anon_pipe, AnonPipe, Pipes}, + }, + sys_common::{FromInner, IntoInner}, +}; + +#[inline] +pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { + anon_pipe(true, false).map(|Pipes { ours, theirs }| (PipeReader(ours), PipeWriter(theirs))) +} + +macro_rules! impl_traits { + ($name:ty) => { + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl AsHandle for $name { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.handle().as_handle() + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl AsRawHandle for $name { + fn as_raw_handle(&self) -> RawHandle { + self.0.handle().as_raw_handle() + } + } + + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl FromRawHandle for $name { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl IntoRawHandle for $name { + fn into_raw_handle(self) -> RawHandle { + self.0.into_handle().into_raw_handle() + } + } + + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl From<$name> for OwnedHandle { + fn from(pipe: $name) -> Self { + Handle::into_inner(AnonPipe::into_inner(pipe.0)) + } + } + #[unstable(feature = "anonymous_pipe", issue = "127154")] + impl From<$name> for Stdio { + fn from(pipe: $name) -> Self { + Self::from(OwnedHandle::from(pipe)) + } + } + }; +} +impl_traits!(PipeReader); +impl_traits!(PipeWriter); + +fn convert_to_pipe(owned_handle: OwnedHandle) -> io::Result { + if unsafe { GetFileType(owned_handle.as_raw_handle()) } == FILE_TYPE_PIPE { + Ok(AnonPipe::from_inner(Handle::from_inner(owned_handle))) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl TryFrom for PipeReader { + type Error = io::Error; + + fn try_from(owned_handle: OwnedHandle) -> Result { + convert_to_pipe(owned_handle).map(Self) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl TryFrom for PipeWriter { + type Error = io::Error; + + fn try_from(owned_handle: OwnedHandle) -> Result { + convert_to_pipe(owned_handle).map(Self) + } +} From d9f09809ce4a22a0e44f197c9dc435a1c7f86113 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 2 Jul 2024 19:22:10 +1000 Subject: [PATCH 17/33] Fix `anonymous_pipe` impl for not supported targets Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/mod.rs | 4 +++- library/std/src/sys/pal/unsupported/pipe.rs | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index 76c4a7c060224..afd07c23ad075 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -7,8 +7,10 @@ pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { cfg_if::cfg_if! { if #[cfg(unix)] { unix::pipe() - } else { + } else if #[cfg(windows)] { windows::pipe() + } else { + panic!("Anonymous pipe is not supported on this target!") } } } diff --git a/library/std/src/sys/pal/unsupported/pipe.rs b/library/std/src/sys/pal/unsupported/pipe.rs index d7d8f297ae586..eaa95594db0b3 100644 --- a/library/std/src/sys/pal/unsupported/pipe.rs +++ b/library/std/src/sys/pal/unsupported/pipe.rs @@ -3,6 +3,10 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; pub struct AnonPipe(!); impl AnonPipe { + pub fn try_clone(&self) -> io::Result { + self.0 + } + pub fn read(&self, _buf: &mut [u8]) -> io::Result { self.0 } From 6c755a32a96c9d49c42d477b5cd5c3ffa82aa8df Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 2 Jul 2024 19:23:34 +1000 Subject: [PATCH 18/33] Optimize: Add `#[inline]` to very simple function Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index afd07c23ad075..f2e0ebc15b1dd 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -51,6 +51,7 @@ macro_rules! forward_io_read_traits { fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { self.0.read_vectored(bufs) } + #[inline] fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } @@ -73,6 +74,7 @@ macro_rules! forward_io_write_traits { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -80,6 +82,8 @@ macro_rules! forward_io_write_traits { fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { self.0.write_vectored(bufs) } + + #[inline] fn is_write_vectored(&self) -> bool { self.0.is_write_vectored() } From 48192701e0385e2f045da79d34bd5e856cf32496 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 7 Jul 2024 00:07:08 +0300 Subject: [PATCH 19/33] use "bootstrap" instead of "rustbuild" in comments and docs Signed-off-by: onur-ozkan --- INSTALL.md | 2 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- compiler/rustc_session/src/config.rs | 2 +- config.example.toml | 8 ++++---- src/bootstrap/README.md | 18 +++++++++--------- src/bootstrap/bootstrap.py | 2 +- src/bootstrap/mk/Makefile.in | 2 +- src/bootstrap/src/bin/main.rs | 2 +- src/bootstrap/src/core/build_steps/compile.rs | 6 +++--- src/bootstrap/src/core/build_steps/doc.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/builder.rs | 8 ++++---- src/bootstrap/src/core/builder/tests.rs | 2 +- src/bootstrap/src/core/config/config.rs | 5 ++--- src/bootstrap/src/core/config/flags.rs | 2 +- src/bootstrap/src/core/sanity.rs | 2 +- src/bootstrap/src/lib.rs | 4 ++-- src/bootstrap/src/utils/helpers.rs | 2 +- src/ci/scripts/install-clang.sh | 2 +- .../x86_64-fortanix-unknown-sgx.md | 2 +- src/tools/build_helper/src/ci.rs | 2 +- src/tools/lint-docs/src/groups.rs | 2 +- src/tools/lint-docs/src/lib.rs | 2 +- .../crates/rust-analyzer/src/version.rs | 2 +- src/tools/rust-installer/src/combiner.rs | 2 +- src/tools/rust-installer/test.sh | 2 +- 26 files changed, 44 insertions(+), 45 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 9619ec2ce5cfa..f660cfb0d7c38 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -215,7 +215,7 @@ python x.py build Right now, building Rust only works with some known versions of Visual Studio. If you have a more recent version installed and the build system doesn't -understand, you may need to force rustbuild to use an older version. +understand, you may need to force bootstrap to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 2bd5dfdce83ee..dd134ebbe6b18 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -398,7 +398,7 @@ impl<'a> GccLinker<'a> { self.link_arg("-dylib"); // Note that the `osx_rpath_install_name` option here is a hack - // purely to support rustbuild right now, we should get a more + // purely to support bootstrap right now, we should get a more // principled solution at some point to force the compiler to pass // the right `-Wl,-install_name` with an `@rpath` in it. if self.sess.opts.cg.rpath || self.sess.opts.unstable_opts.osx_rpath_install_name { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 41c99f7edeeff..e748d1ff47b63 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2620,7 +2620,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // This is the location used by the `rust-src` `rustup` component. let mut candidate = sysroot.join("lib/rustlib/src/rust"); if let Ok(metadata) = candidate.symlink_metadata() { - // Replace the symlink rustbuild creates, with its destination. + // Replace the symlink bootstrap creates, with its destination. // We could try to use `fs::canonicalize` instead, but that might // produce unnecessarily verbose path. if metadata.file_type().is_symlink() { diff --git a/config.example.toml b/config.example.toml index 679abcdc7771b..68c632d91cdec 100644 --- a/config.example.toml +++ b/config.example.toml @@ -1,6 +1,6 @@ # Sample TOML configuration file for building Rust. # -# To configure rustbuild, run `./configure` or `./x.py setup`. +# To configure bootstrap, run `./configure` or `./x.py setup`. # See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-configtoml for more information. # # All options are commented out by default in this file, and they're commented @@ -109,7 +109,7 @@ # increases the size of binaries and consequently the memory required by # each linker process. # If set to 0, linker invocations are treated like any other job and -# controlled by rustbuild's -j parameter. +# controlled by bootstrap's -j parameter. #link-jobs = 0 # Whether to build LLVM as a dynamically linked library (as opposed to statically linked). @@ -371,11 +371,11 @@ # Useful for modifying only the stage2 compiler without having to pass `--keep-stage 0` each time. #local-rebuild = false -# Print out how long each rustbuild step took (mostly intended for CI and +# Print out how long each bootstrap step took (mostly intended for CI and # tracking over time) #print-step-timings = false -# Print out resource usage data for each rustbuild step, as defined by the Unix +# Print out resource usage data for each bootstrap step, as defined by the Unix # struct rusage. (Note that this setting is completely unstable: the data it # captures, what platforms it supports, the format of its associated output, and # this setting's very existence, are all subject to change.) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index fb3c862704306..0ac58645d2dfc 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -1,7 +1,7 @@ -# rustbuild - Bootstrapping Rust +# Bootstrapping Rust This README is aimed at helping to explain how Rust is bootstrapped, -and some of the technical details of the build system. +and some of the technical details of the bootstrap build system. Note that this README only covers internal information, not how to use the tool. Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information. @@ -12,17 +12,17 @@ Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further info The build system defers most of the complicated logic of managing invocations of rustc and rustdoc to Cargo itself. However, moving through various stages -and copying artifacts is still necessary for it to do. Each time rustbuild +and copying artifacts is still necessary for it to do. Each time bootstrap is invoked, it will iterate through the list of predefined steps and execute each serially in turn if it matches the paths passed or is a default rule. -For each step, rustbuild relies on the step internally being incremental and -parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded +For each step, bootstrap relies on the step internally being incremental and +parallel. Note, though, that the `-j` parameter to bootstrap gets forwarded to appropriate test harnesses and such. ## Build phases -The rustbuild build system goes through a few phases to actually build the -compiler. What actually happens when you invoke rustbuild is: +Bootstrap build system goes through a few phases to actually build the +compiler. What actually happens when you invoke bootstrap is: 1. The entry point script (`x` for unix like systems, `x.ps1` for windows systems, `x.py` cross-platform) is run. This script is responsible for downloading the stage0 @@ -151,9 +151,9 @@ build/ stage3/ ``` -## Extending rustbuild +## Extending bootstrap -When you use the bootstrap system, you'll call it through the entry point script +When you use bootstrap, you'll call it through the entry point script (`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`. `bootstrap` has a difficult problem: it is written in Rust, but yet it is run before the Rust compiler is built! To work around this, there are two components diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 7e47b373ff9df..4e8e0fd2532f1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1038,7 +1038,7 @@ def build_triple(self): def check_vendored_status(self): """Check that vendoring is configured properly""" - # keep this consistent with the equivalent check in rustbuild: + # keep this consistent with the equivalent check in bootstrap: # https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/lib.rs#L399-L405 if 'SUDO_USER' in os.environ and not self.use_vendored_sources: if os.getuid() == 0: diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index cab37e0da4736..f85aefcb268d3 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -20,7 +20,7 @@ all: $(Q)$(BOOTSTRAP) doc --stage 2 $(BOOTSTRAP_ARGS) help: - $(Q)echo 'Welcome to the rustbuild build system!' + $(Q)echo 'Welcome to bootstrap, the Rust build system!' $(Q)echo $(Q)echo This makefile is a thin veneer over the ./x.py script located $(Q)echo in this directory. To get the full power of the build system diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 44fb1911fc6d3..a7d21ba6ae127 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -1,4 +1,4 @@ -//! rustbuild, the Rust build system +//! bootstrap, the Rust build system //! //! This is the entry point for the build system used to compile the `rustc` //! compiler. Lots of documentation can be found in the `README.md` file in the diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 01b25224de4cd..9d79baf45e5c5 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1,7 +1,7 @@ //! Implementation of compiling various phases of the compiler and standard //! library. //! -//! This module contains some of the real meat in the rustbuild build system +//! This module contains some of the real meat in the bootstrap build system //! which is where Cargo is used to compile the standard library, libtest, and //! the compiler. This module is also responsible for assembling the sysroot as it //! goes along from the output of the previous stage. @@ -819,8 +819,8 @@ pub struct Rustc { pub compiler: Compiler, /// Whether to build a subset of crates, rather than the whole compiler. /// - /// This should only be requested by the user, not used within rustbuild itself. - /// Using it within rustbuild can lead to confusing situation where lints are replayed + /// This should only be requested by the user, not used within bootstrap itself. + /// Using it within bootstrap can lead to confusing situation where lints are replayed /// in two different steps. crates: Vec, } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 823e842693e96..38d4f0bed4ccd 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1,4 +1,4 @@ -//! Documentation generation for rustbuilder. +//! Documentation generation for bootstrap. //! //! This module implements generation for all bits and pieces of documentation //! for the Rust project. This notably includes suites like the rust book, the diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index dc53bd3cfa785..5ea711ebcd602 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2993,7 +2993,7 @@ impl Step for Bootstrap { // https://github.com/rust-lang/rust/issues/49215 cmd.env("RUSTFLAGS", flags); } - // rustbuild tests are racy on directory creation so just run them one at a time. + // bootstrap tests are racy on directory creation so just run them one at a time. // Since there's not many this shouldn't be a problem. run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", None, compiler, host, builder); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 4da912994c3ee..0ea28728e0d45 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1627,11 +1627,11 @@ impl<'a> Builder<'a> { } // This tells Cargo (and in turn, rustc) to output more complete - // dependency information. Most importantly for rustbuild, this + // dependency information. Most importantly for bootstrap, this // includes sysroot artifacts, like libstd, which means that we don't - // need to track those in rustbuild (an error prone process!). This + // need to track those in bootstrap (an error prone process!). This // feature is currently unstable as there may be some bugs and such, but - // it represents a big improvement in rustbuild's reliability on + // it represents a big improvement in bootstrap's reliability on // rebuilds, so we're using it here. // // For some additional context, see #63470 (the PR originally adding @@ -1643,7 +1643,7 @@ impl<'a> Builder<'a> { // Restrict the allowed features so we don't depend on nightly // accidentally. // - // binary-dep-depinfo is used by rustbuild itself for all + // binary-dep-depinfo is used by bootstrap itself for all // compilations. // // Lots of tools depend on proc_macro2 and proc-macro-error. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index aa119b8c69912..97c9ece0036ea 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -266,7 +266,7 @@ mod defaults { // rustdoc/rustcc/std here (the user only requested a host=B build, so // there's not really a need for us to build for target A in this case // (since we're producing stage 1 libraries/binaries). But currently - // rustbuild is just a bit buggy here; this should be fixed though. + // bootstrap is just a bit buggy here; this should be fixed though. assert_eq!( first(cache.all::()), &[ diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 10ac6c93e9a43..508f7350b51c7 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -658,8 +658,7 @@ impl Merge for TomlConfig { } } -// We are using a decl macro instead of a derive proc macro here to reduce the compile time of -// rustbuild. +// We are using a decl macro instead of a derive proc macro here to reduce the compile time of bootstrap. macro_rules! define_config { ($(#[$attr:meta])* struct $name:ident { $($field:ident: Option<$field_ty:ty> = $field_key:literal,)* @@ -704,7 +703,7 @@ macro_rules! define_config { // The following is a trimmed version of what serde_derive generates. All parts not relevant // for toml deserialization have been removed. This reduces the binary size and improves - // compile time of rustbuild. + // compile time of bootstrap. impl<'de> Deserialize<'de> for $name { fn deserialize(deserializer: D) -> Result where diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index aeb608a9ea26b..19f752da81c13 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -1,4 +1,4 @@ -//! Command-line interface of the rustbuild build system. +//! Command-line interface of the bootstrap build system. //! //! This module implements the command-line parsing of the build system which //! has various flags to configure how it's run. diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 78862ccb8cd68..c70f879568d14 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -1,4 +1,4 @@ -//! Sanity checking performed by rustbuild before actually executing anything. +//! Sanity checking performed by bootstrap before actually executing anything. //! //! This module contains the implementation of ensuring that the build //! environment looks reasonable before progressing. This will verify that diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index ffdd9bc885a62..e08eb4e62bb9a 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1,9 +1,9 @@ -//! Implementation of rustbuild, the Rust build system. +//! Implementation of bootstrap, the Rust build system. //! //! This module, and its descendants, are the implementation of the Rust build //! system. Most of this build system is backed by Cargo but the outer layer //! here serves as the ability to orchestrate calling Cargo, sequencing Cargo -//! builds, building artifacts like LLVM, etc. The goals of rustbuild are: +//! builds, building artifacts like LLVM, etc. The goals of bootstrap are: //! //! * To be an easily understandable, easily extensible, and maintainable build //! system. diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 2575b7939b44c..a52b4bbf98867 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -1,4 +1,4 @@ -//! Various utility functions used throughout rustbuild. +//! Various utility functions used throughout bootstrap. //! //! Simple things like testing the various filesystem operations here and there, //! not a lot of interesting happenings here unfortunately. diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 24b9904d65c25..6103aa61248ae 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -40,7 +40,7 @@ if isMacOS; then # our own clang can figure out the correct include path on its own. ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" - # Configure `AR` specifically so rustbuild doesn't try to infer it as + # Configure `AR` specifically so bootstrap doesn't try to infer it as # `clang-ar` by accident. ciCommandSetEnv AR "ar" elif isWindows && ! isKnownToBeMingwBuild; then diff --git a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md index 97b5827c1443f..33e1c44e6d351 100644 --- a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md +++ b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md @@ -46,7 +46,7 @@ on how to setup a development and runtime environment. As a tier 2 target, the target is built by the Rust project. -You can configure rustbuild like so: +You can configure bootstrap like so: ```toml [build] diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs index 09489b0d9b7da..233fed4151c19 100644 --- a/src/tools/build_helper/src/ci.rs +++ b/src/tools/build_helper/src/ci.rs @@ -25,7 +25,7 @@ impl CiEnv { /// If in a CI environment, forces the command to run with colors. pub fn force_coloring_in_ci(self, cmd: &mut Command) { if self != CiEnv::None { - // Due to use of stamp/docker, the output stream of rustbuild is not + // Due to use of stamp/docker, the output stream of bootstrap is not // a TTY in CI, so coloring is by-default turned off. // The explicit `TERM=xterm` environment is needed for // `--color always` to actually work. This env var was lost when diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index f246d71d499b4..9eaa234bfaf30 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -37,7 +37,7 @@ impl<'a> LintExtractor<'a> { .map_err(|e| format!("could not read {}: {}", groups_path.display(), e))?; let new_contents = contents.replace("{{groups-table}}", &self.make_groups_table(lints, &groups)?); - // Delete the output because rustbuild uses hard links in its copies. + // Delete the output because bootstrap uses hard links in its copies. let _ = fs::remove_file(&groups_path); fs::write(&groups_path, new_contents) .map_err(|e| format!("could not write to {}: {}", groups_path.display(), e))?; diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 72d6a495e7e79..48e2dd098769e 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -532,7 +532,7 @@ impl<'a> LintExtractor<'a> { } add_rename_redirect(level, &mut result); let out_path = self.out_path.join("listing").join(level.doc_filename()); - // Delete the output because rustbuild uses hard links in its copies. + // Delete the output because bootstrap uses hard links in its copies. let _ = fs::remove_file(&out_path); fs::write(&out_path, result) .map_err(|e| format!("could not write to {}: {}", out_path.display(), e))?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/version.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/version.rs index 1e829299e6f3c..2ff967416c006 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/version.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/version.rs @@ -15,7 +15,7 @@ pub struct VersionInfo { pub version: &'static str, /// The release channel we were built for (stable/beta/nightly/dev). /// - /// `None` if not built via rustbuild. + /// `None` if not built via bootstrap. pub release_channel: Option<&'static str>, /// Information about the Git repository we may have been built from. /// diff --git a/src/tools/rust-installer/src/combiner.rs b/src/tools/rust-installer/src/combiner.rs index c211b34850a07..e7020980dc3d6 100644 --- a/src/tools/rust-installer/src/combiner.rs +++ b/src/tools/rust-installer/src/combiner.rs @@ -109,7 +109,7 @@ impl Combiner { .with_context(|| format!("failed to read components in '{}'", input_tarball))?; for component in pkg_components.split_whitespace() { // All we need to do is copy the component directory. We could - // move it, but rustbuild wants to reuse the unpacked package + // move it, but bootstrap wants to reuse the unpacked package // dir for OS-specific installers on macOS and Windows. let component_dir = package_dir.join(component); create_dir(&component_dir)?; diff --git a/src/tools/rust-installer/test.sh b/src/tools/rust-installer/test.sh index 16b05c66197c8..7b3e745600629 100755 --- a/src/tools/rust-installer/test.sh +++ b/src/tools/rust-installer/test.sh @@ -974,7 +974,7 @@ combined_remains() { --package-name=rust \ --input-tarballs="$OUT_DIR/rustc.tar.gz,$OUT_DIR/cargo.tar.gz,$OUT_DIR/rust-docs.tar.gz" for component in rustc cargo rust-docs; do - # rustbuild wants the original extracted package intact too + # bootstrap wants the original extracted package intact too try test -d "$WORK_DIR/$component/$component" try test -d "$WORK_DIR/rust/$component" done From 99721c84691b3ee7339d307c92a762414527143d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Jul 2024 16:53:10 +1000 Subject: [PATCH 20/33] Clear `inner_attr_ranges` regularly. There's a comment saying we don't do it for performance reasons, but it doesn't actually affect performance. The commit also tweaks the control flow, to make clearer that two code paths are mutually exclusive. --- compiler/rustc_parse/src/parser/attr_wrapper.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 38f18022e3c58..e9aece13b2e68 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -352,15 +352,10 @@ impl<'a> Parser<'a> { let target = AttrsTarget { attrs: final_attrs.iter().cloned().collect(), tokens }; self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target))); self.capture_state.replace_ranges.extend(inner_attr_replace_ranges); - } - - // Only clear our `replace_ranges` when we're finished capturing entirely. - if matches!(self.capture_state.capturing, Capturing::No) { + } else if matches!(self.capture_state.capturing, Capturing::No) { + // Only clear the ranges once we've finished capturing entirely. self.capture_state.replace_ranges.clear(); - // We don't clear `inner_attr_ranges`, as doing so repeatedly - // had a measurable performance impact. Most inner attributes that - // we insert will get removed - when we drop the parser, we'll free - // up the memory used by any attributes that we didn't remove from the map. + self.capture_state.inner_attr_ranges.clear(); } Ok(ret) } From d15cee549cafe4b47669bc722c2beec959ce73c8 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 9 Jul 2024 22:46:41 +1000 Subject: [PATCH 21/33] Refactor: Make `AcessMode` an enum` Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/unix.rs | 4 ++-- library/std/src/sys/pal/unix/fd.rs | 28 +++++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 0438d933a06c0..2e1d8b0094638 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -77,7 +77,7 @@ impl TryFrom for PipeReader { fn try_from(owned_fd: OwnedFd) -> Result { convert_to_pipe(owned_fd) .and_then(|pipe| { - if pipe.as_file_desc().get_access_mode()?.readable { + if pipe.as_file_desc().get_access_mode()?.is_readable() { Ok(pipe) } else { Err(io::Error::new( @@ -97,7 +97,7 @@ impl TryFrom for PipeWriter { fn try_from(owned_fd: OwnedFd) -> Result { convert_to_pipe(owned_fd) .and_then(|pipe| { - if pipe.as_file_desc().get_access_mode()?.writable { + if pipe.as_file_desc().get_access_mode()?.is_writable() { Ok(pipe) } else { Err(io::Error::new( diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index d889a95f891a7..2536dd845548d 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -26,9 +26,22 @@ use libc::off64_t; )))] use libc::off_t as off64_t; -pub struct AccessMode { - pub readable: bool, - pub writable: bool, +#[derive(Copy, Clone)] +pub enum AccessMode { + ReadOnly, + WriteOnly, + ReadWrite, + None, +} + +impl AccessMode { + pub fn is_readable(self) -> bool { + matches!(self, AccessMode::ReadOnly | AccessMode::ReadWrite) + } + + pub fn is_writable(self) -> bool { + matches!(self, AccessMode::WriteOnly | AccessMode::ReadWrite) + } } #[derive(Debug)] @@ -529,9 +542,12 @@ impl FileDesc { pub fn get_access_mode(&self) -> io::Result { let access_mode = self.get_flags()? & libc::O_ACCMODE; - Ok(AccessMode { - readable: access_mode == libc::O_RDWR || access_mode == libc::O_RDONLY, - writable: access_mode == libc::O_RDWR || access_mode == libc::O_WRONLY, + Ok(match access_mode { + libc::O_RDWR => AccessMode::ReadWrite, + libc::O_RDONLY => AccessMode::ReadOnly, + libc::O_WRONLY => AccessMode::WriteOnly, + + _ => AccessMode::None, }) } From e22dd1adc2b250f927b666d0260bc23008cbcdcf Mon Sep 17 00:00:00 2001 From: Jiahao XU <30436523+NobodyXu@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:27:58 +1000 Subject: [PATCH 22/33] Update mod.rs Co-authored-by: Alphyr <47725341+a1phyr@users.noreply.github.com> --- library/std/src/sys/anonymous_pipe/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index f2e0ebc15b1dd..5b60e6b51d6b6 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -10,7 +10,7 @@ pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { } else if #[cfg(windows)] { windows::pipe() } else { - panic!("Anonymous pipe is not supported on this target!") + Err(io::Error::UNSUPPORTED_PLATFORM) } } } From 100fe5cbd323062f6a8cf95100b7fb9e9cd00dea Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Wed, 10 Jul 2024 23:20:12 +1000 Subject: [PATCH 23/33] Move `std::net::pip*` to a new mod `std::pipe` Signed-off-by: Jiahao XU --- library/std/src/lib.rs | 3 +++ library/std/src/net/mod.rs | 2 -- library/std/src/sys/anonymous_pipe/mod.rs | 10 ++++++++++ library/std/src/sys/mod.rs | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 27ed2e4137c7e..b08d903fefda4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -685,6 +685,9 @@ pub use core::{ module_path, option_env, stringify, trace_macros, }; +#[unstable(feature = "anonymous_pipe", issue = "127154")] +pub use crate::sys::anonymous_pipe as pipe; + #[unstable( feature = "concat_bytes", issue = "87555", diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index cacf8c01f672d..858776f14466a 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -33,8 +33,6 @@ pub use self::tcp::IntoIncoming; pub use self::tcp::{Incoming, TcpListener, TcpStream}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::udp::UdpSocket; -#[unstable(feature = "anonymous_pipe", issue = "127154")] -pub use crate::sys::anonymous_pipe::{pipe, PipeReader, PipeWriter}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::net::AddrParseError; diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index 5b60e6b51d6b6..3f660b8b21995 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -1,3 +1,13 @@ +//! Module for annoymous pipe +//! +//! ``` +//! #![feature(anonymous_pipe)] +//! # fn main() -> std::io::Result<()> { +//! let (reader, writer) = std::pipe::pipe()?; +//! # Ok(()) +//! # } +//! ``` + use crate::{io, process::Stdio, sys::pipe::AnonPipe}; /// Create annoymous pipe that is close-on-exec and blocking. diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index fad01f581577d..f7b41a2d4064a 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -5,6 +5,7 @@ mod pal; mod personality; +#[unstable(feature = "anonymous_pipe", issue = "127154")] pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; From 62b846ebe420574febdceb01ede043fd959818c6 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Wed, 10 Jul 2024 23:49:53 +1000 Subject: [PATCH 24/33] Remove use of `macro_rules!` Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/mod.rs | 126 +++++++++++------- library/std/src/sys/anonymous_pipe/unix.rs | 115 ++++++++++------ library/std/src/sys/anonymous_pipe/windows.rs | 117 ++++++++++------ 3 files changed, 225 insertions(+), 133 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index 3f660b8b21995..118bcbaa75bf7 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -51,57 +51,85 @@ impl PipeWriter { } } -macro_rules! forward_io_read_traits { - ($name:ty) => { - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl io::Read for $name { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { - self.0.read_vectored(bufs) - } - #[inline] - fn is_read_vectored(&self) -> bool { - self.0.is_read_vectored() - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.0.read_to_end(buf) - } - fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { - self.0.read_buf(buf) - } - } - }; +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Read for &PipeReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.0.read_to_end(buf) + } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } } -forward_io_read_traits!(PipeReader); -forward_io_read_traits!(&PipeReader); - -macro_rules! forward_io_write_traits { - ($name:ty) => { - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl io::Write for $name { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - #[inline] - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { - self.0.write_vectored(bufs) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - self.0.is_write_vectored() - } - } - }; + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Read for PipeReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.0.read_to_end(buf) + } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Write for &PipeWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Write for PipeWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } } -forward_io_write_traits!(PipeWriter); -forward_io_write_traits!(&PipeWriter); #[cfg(unix)] mod unix; diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 2e1d8b0094638..8ab36dea4cdd2 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -18,48 +18,79 @@ pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { anon_pipe().map(|(rx, tx)| (PipeReader(rx), PipeWriter(tx))) } -macro_rules! impl_traits { - ($name:ty) => { - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsFd for $name { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsRawFd for $name { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for OwnedFd { - fn from(pipe: $name) -> Self { - FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl FromRawFd for $name { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(AnonPipe::from_raw_fd(raw_fd)) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl IntoRawFd for $name { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for Stdio { - fn from(pipe: $name) -> Self { - Self::from(OwnedFd::from(pipe)) - } - } - }; -} -impl_traits!(PipeReader); -impl_traits!(PipeWriter); +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsFd for PipeReader { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsRawFd for PipeReader { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for OwnedFd { + fn from(pipe: PipeReader) -> Self { + FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl FromRawFd for PipeReader { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self(AnonPipe::from_raw_fd(raw_fd)) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl IntoRawFd for PipeReader { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for Stdio { + fn from(pipe: PipeReader) -> Self { + Self::from(OwnedFd::from(pipe)) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsFd for PipeWriter { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsRawFd for PipeWriter { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for OwnedFd { + fn from(pipe: PipeWriter) -> Self { + FileDesc::into_inner(AnonPipe::into_inner(pipe.0)) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl FromRawFd for PipeWriter { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self(AnonPipe::from_raw_fd(raw_fd)) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl IntoRawFd for PipeWriter { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for Stdio { + fn from(pipe: PipeWriter) -> Self { + Self::from(OwnedFd::from(pipe)) + } +} fn convert_to_pipe(owned_fd: OwnedFd) -> io::Result { let file = File::from(owned_fd); diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index cd132c5a60f41..f107258ff8ddb 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -17,50 +17,83 @@ pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> { anon_pipe(true, false).map(|Pipes { ours, theirs }| (PipeReader(ours), PipeWriter(theirs))) } -macro_rules! impl_traits { - ($name:ty) => { - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsHandle for $name { - fn as_handle(&self) -> BorrowedHandle<'_> { - self.0.handle().as_handle() - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl AsRawHandle for $name { - fn as_raw_handle(&self) -> RawHandle { - self.0.handle().as_raw_handle() - } - } +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsHandle for PipeReader { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.handle().as_handle() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsRawHandle for PipeReader { + fn as_raw_handle(&self) -> RawHandle { + self.0.handle().as_raw_handle() + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl FromRawHandle for PipeReader { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl IntoRawHandle for PipeReader { + fn into_raw_handle(self) -> RawHandle { + self.0.into_handle().into_raw_handle() + } +} - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl FromRawHandle for $name { - unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl IntoRawHandle for $name { - fn into_raw_handle(self) -> RawHandle { - self.0.into_handle().into_raw_handle() - } - } +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for OwnedHandle { + fn from(pipe: PipeReader) -> Self { + Handle::into_inner(AnonPipe::into_inner(pipe.0)) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for Stdio { + fn from(pipe: PipeReader) -> Self { + Self::from(OwnedHandle::from(pipe)) + } +} - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for OwnedHandle { - fn from(pipe: $name) -> Self { - Handle::into_inner(AnonPipe::into_inner(pipe.0)) - } - } - #[unstable(feature = "anonymous_pipe", issue = "127154")] - impl From<$name> for Stdio { - fn from(pipe: $name) -> Self { - Self::from(OwnedHandle::from(pipe)) - } - } - }; -} -impl_traits!(PipeReader); -impl_traits!(PipeWriter); +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsHandle for PipeWriter { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.handle().as_handle() + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl AsRawHandle for PipeWriter { + fn as_raw_handle(&self) -> RawHandle { + self.0.handle().as_raw_handle() + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl FromRawHandle for PipeWriter { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle))) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl IntoRawHandle for PipeWriter { + fn into_raw_handle(self) -> RawHandle { + self.0.into_handle().into_raw_handle() + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for OwnedHandle { + fn from(pipe: PipeWriter) -> Self { + Handle::into_inner(AnonPipe::into_inner(pipe.0)) + } +} +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl From for Stdio { + fn from(pipe: PipeWriter) -> Self { + Self::from(OwnedHandle::from(pipe)) + } +} fn convert_to_pipe(owned_handle: OwnedHandle) -> io::Result { if unsafe { GetFileType(owned_handle.as_raw_handle()) } == FILE_TYPE_PIPE { From 4547b30b4a2751ac857dd2da5ce758ea520df243 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Thu, 11 Jul 2024 00:08:34 +1000 Subject: [PATCH 25/33] Replace `TryFrom` with `From` Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/tests.rs | 99 ------------------- library/std/src/sys/anonymous_pipe/unix.rs | 53 ++-------- library/std/src/sys/anonymous_pipe/windows.rs | 25 ++--- library/std/src/sys/pal/unix/fd.rs | 50 +++------- 4 files changed, 28 insertions(+), 199 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe/tests.rs b/library/std/src/sys/anonymous_pipe/tests.rs index 048e011fc5eaf..8f17422901d62 100644 --- a/library/std/src/sys/anonymous_pipe/tests.rs +++ b/library/std/src/sys/anonymous_pipe/tests.rs @@ -27,102 +27,3 @@ fn pipe_try_clone_and_rw() { rx.read_to_string(&mut s).unwrap(); assert_eq!(s, "45"); } - -#[cfg(unix)] -mod unix_specific { - use super::*; - - use crate::{ - fs::File, - io, - os::fd::{AsRawFd, OwnedFd}, - }; - - #[test] - fn pipe_owned_fd_round_trip_conversion() { - let (rx, tx) = pipe().unwrap(); - let raw_fds = (rx.as_raw_fd(), tx.as_raw_fd()); - let (rx_owned_fd, tx_owned_fd) = (OwnedFd::from(rx), OwnedFd::from(tx)); - - let rx = PipeReader::try_from(rx_owned_fd).unwrap(); - let tx = PipeWriter::try_from(tx_owned_fd).unwrap(); - assert_eq!(raw_fds, (rx.as_raw_fd(), tx.as_raw_fd())); - } - - #[test] - fn convert_from_non_pipe_to_pipe_reader_shall_fail() { - let file = File::open("/dev/zero").unwrap(); - let err = PipeReader::try_from(OwnedFd::from(file)).unwrap_err(); - - assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); - } - - #[test] - fn convert_from_non_pipe_to_pipe_writer_shall_fail() { - let file = File::options().write(true).open("/dev/null").unwrap(); - let err = PipeWriter::try_from(OwnedFd::from(file)).unwrap_err(); - - assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); - } - - #[test] - fn convert_pipe_writer_to_pipe_reader_shall_fail() { - let (_, tx) = pipe().unwrap(); - let fd = tx.as_raw_fd(); - let err = PipeReader::try_from(OwnedFd::from(tx)).unwrap_err(); - - assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - assert_eq!(format!("{}", err.get_ref().unwrap()), format!("Pipe {fd} is not readable")); - } - - #[test] - fn convert_pipe_reader_to_pipe_writer_shall_fail() { - let (rx, _) = pipe().unwrap(); - let fd = rx.as_raw_fd(); - let err = PipeWriter::try_from(OwnedFd::from(rx)).unwrap_err(); - - assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - assert_eq!(format!("{}", err.get_ref().unwrap()), format!("Pipe {fd} is not writable")); - } -} - -#[cfg(windows)] -mod windows_specific { - use super::*; - - use crate::{ - io, - os::windows::io::{AsHandle, AsRawHandle, OwnedHandle}, - }; - - #[test] - fn pipe_owned_handle_round_trip_conversion() { - let (rx, tx) = pipe().unwrap(); - let raw_handles = (rx.as_raw_handle(), tx.as_raw_handle()); - let (rx_owned_handle, tx_owned_handle) = (OwnedHandle::from(rx), OwnedHandle::from(tx)); - - let rx = PipeReader::try_from(rx_owned_handle).unwrap(); - let tx = PipeWriter::try_from(tx_owned_handle).unwrap(); - assert_eq!(raw_handles, (rx.as_raw_handle(), tx.as_raw_handle())); - } - - #[test] - fn convert_from_non_pipe_to_pipe_reader_shall_fail() { - let file = io::stdin().as_handle().try_clone_to_owned().unwrap(); - let err = PipeReader::try_from(OwnedHandle::from(file)).unwrap_err(); - - assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); - } - - #[test] - fn convert_from_non_pipe_to_pipe_writer_shall_fail() { - let file = io::stdout().as_handle().try_clone_to_owned().unwrap(); - let err = PipeWriter::try_from(OwnedHandle::from(file)).unwrap_err(); - - assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - assert_eq!(format!("{}", err.get_ref().unwrap()), "Not a pipe"); - } -} diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 8ab36dea4cdd2..18252f0183d3b 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -1,11 +1,7 @@ use super::*; use crate::{ - fs::File, - os::{ - fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, - unix::fs::FileTypeExt, - }, + os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, sys::{ fd::FileDesc, pipe::{anon_pipe, AnonPipe}, @@ -92,51 +88,20 @@ impl From for Stdio { } } -fn convert_to_pipe(owned_fd: OwnedFd) -> io::Result { - let file = File::from(owned_fd); - if file.metadata()?.file_type().is_fifo() { - Ok(AnonPipe::from_inner(FileDesc::from_inner(OwnedFd::from(file)))) - } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) - } +fn convert_to_pipe(owned_fd: OwnedFd) -> AnonPipe { + AnonPipe::from_inner(FileDesc::from_inner(OwnedFd::from(owned_fd))) } #[unstable(feature = "anonymous_pipe", issue = "127154")] -impl TryFrom for PipeReader { - type Error = io::Error; - - fn try_from(owned_fd: OwnedFd) -> Result { - convert_to_pipe(owned_fd) - .and_then(|pipe| { - if pipe.as_file_desc().get_access_mode()?.is_readable() { - Ok(pipe) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("Pipe {} is not readable", pipe.as_raw_fd()), - )) - } - }) - .map(Self) +impl From for PipeReader { + fn from(owned_fd: OwnedFd) -> Self { + Self(convert_to_pipe(owned_fd)) } } #[unstable(feature = "anonymous_pipe", issue = "127154")] -impl TryFrom for PipeWriter { - type Error = io::Error; - - fn try_from(owned_fd: OwnedFd) -> Result { - convert_to_pipe(owned_fd) - .and_then(|pipe| { - if pipe.as_file_desc().get_access_mode()?.is_writable() { - Ok(pipe) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("Pipe {} is not writable", pipe.as_raw_fd()), - )) - } - }) - .map(Self) +impl From for PipeWriter { + fn from(owned_fd: OwnedFd) -> Self { + Self(convert_to_pipe(owned_fd)) } } diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index f107258ff8ddb..592e2f05a9ebf 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -5,7 +5,6 @@ use crate::{ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, }, sys::{ - c::{GetFileType, FILE_TYPE_PIPE}, handle::Handle, pipe::{anon_pipe, AnonPipe, Pipes}, }, @@ -95,28 +94,20 @@ impl From for Stdio { } } -fn convert_to_pipe(owned_handle: OwnedHandle) -> io::Result { - if unsafe { GetFileType(owned_handle.as_raw_handle()) } == FILE_TYPE_PIPE { - Ok(AnonPipe::from_inner(Handle::from_inner(owned_handle))) - } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "Not a pipe")) - } +fn convert_to_pipe(owned_handle: OwnedHandle) -> AnonPipe { + AnonPipe::from_inner(Handle::from_inner(owned_handle)) } #[unstable(feature = "anonymous_pipe", issue = "127154")] -impl TryFrom for PipeReader { - type Error = io::Error; - - fn try_from(owned_handle: OwnedHandle) -> Result { - convert_to_pipe(owned_handle).map(Self) +impl From for PipeReader { + fn from(owned_handle: OwnedHandle) -> Self { + Self(convert_to_pipe(owned_handle)) } } #[unstable(feature = "anonymous_pipe", issue = "127154")] -impl TryFrom for PipeWriter { - type Error = io::Error; - - fn try_from(owned_handle: OwnedHandle) -> Result { - convert_to_pipe(owned_handle).map(Self) +impl From for PipeWriter { + fn from(owned_handle: OwnedHandle) -> Self { + Self(convert_to_pipe(owned_handle)) } } diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index 2536dd845548d..1701717db597c 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -26,24 +26,6 @@ use libc::off64_t; )))] use libc::off_t as off64_t; -#[derive(Copy, Clone)] -pub enum AccessMode { - ReadOnly, - WriteOnly, - ReadWrite, - None, -} - -impl AccessMode { - pub fn is_readable(self) -> bool { - matches!(self, AccessMode::ReadOnly | AccessMode::ReadWrite) - } - - pub fn is_writable(self) -> bool { - matches!(self, AccessMode::WriteOnly | AccessMode::ReadWrite) - } -} - #[derive(Debug)] pub struct FileDesc(OwnedFd); @@ -536,30 +518,20 @@ impl FileDesc { } } - fn get_flags(&self) -> io::Result { - unsafe { cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL)) } - } - - pub fn get_access_mode(&self) -> io::Result { - let access_mode = self.get_flags()? & libc::O_ACCMODE; - Ok(match access_mode { - libc::O_RDWR => AccessMode::ReadWrite, - libc::O_RDONLY => AccessMode::ReadOnly, - libc::O_WRONLY => AccessMode::WriteOnly, - - _ => AccessMode::None, - }) - } - #[cfg(not(target_os = "linux"))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - let previous = self.get_flags()?; - let new = - if nonblocking { previous | libc::O_NONBLOCK } else { previous & !libc::O_NONBLOCK }; - if new != previous { - unsafe { cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new)) }?; + unsafe { + let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL))?; + let new = if nonblocking { + previous | libc::O_NONBLOCK + } else { + previous & !libc::O_NONBLOCK + }; + if new != previous { + cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new))?; + } + Ok(()) } - Ok(()) } #[inline] From 72f5999438a47339de0ef9c3f63eec445d2e077e Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Fri, 12 Jul 2024 00:11:14 +1000 Subject: [PATCH 26/33] Fix compilation on non-unix, non-windows targets Signed-off-by: Jiahao XU --- library/std/src/sys/pal/unsupported/pipe.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/unsupported/pipe.rs b/library/std/src/sys/pal/unsupported/pipe.rs index eaa95594db0b3..9599665fdc697 100644 --- a/library/std/src/sys/pal/unsupported/pipe.rs +++ b/library/std/src/sys/pal/unsupported/pipe.rs @@ -1,5 +1,6 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +#[derive(Debug)] pub struct AnonPipe(!); impl AnonPipe { From 45886ccbe0629d483cf0893975481ce39a0f02bd Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Fri, 12 Jul 2024 23:34:31 +1000 Subject: [PATCH 27/33] Fix compilation error on unsupported target Signed-off-by: Jiahao XU --- library/std/src/sys/anonymous_pipe/mod.rs | 2 +- library/std/src/sys/anonymous_pipe/unix.rs | 1 + library/std/src/sys/anonymous_pipe/windows.rs | 1 + library/std/src/sys/pal/unsupported/pipe.rs | 12 ++++++++++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index 118bcbaa75bf7..07c5f74aec414 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -8,7 +8,7 @@ //! # } //! ``` -use crate::{io, process::Stdio, sys::pipe::AnonPipe}; +use crate::{io, sys::pipe::AnonPipe}; /// Create annoymous pipe that is close-on-exec and blocking. #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 18252f0183d3b..833f210dc65b6 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -2,6 +2,7 @@ use super::*; use crate::{ os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, + process::Stdio, sys::{ fd::FileDesc, pipe::{anon_pipe, AnonPipe}, diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index 592e2f05a9ebf..d5398c3cc9ca8 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -4,6 +4,7 @@ use crate::{ os::windows::io::{ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, }, + process::Stdio, sys::{ handle::Handle, pipe::{anon_pipe, AnonPipe, Pipes}, diff --git a/library/std/src/sys/pal/unsupported/pipe.rs b/library/std/src/sys/pal/unsupported/pipe.rs index 9599665fdc697..781eafe2f1a6b 100644 --- a/library/std/src/sys/pal/unsupported/pipe.rs +++ b/library/std/src/sys/pal/unsupported/pipe.rs @@ -1,8 +1,16 @@ -use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::{ + fmt, + io::{self, BorrowedCursor, IoSlice, IoSliceMut}, +}; -#[derive(Debug)] pub struct AnonPipe(!); +impl fmt::Debug for AnonPipe { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0 + } +} + impl AnonPipe { pub fn try_clone(&self) -> io::Result { self.0 From 7fc69436a1226b254b3b6f9ed8c6d54965e0cfbf Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 12 Jul 2024 13:49:41 -0400 Subject: [PATCH 28/33] Use ManuallyDrop in BufWriter::into_parts --- library/std/src/io/buffered/bufwriter.rs | 14 +++++++------- library/std/src/io/buffered/tests.rs | 10 ++++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 2d13230ffbabd..1768bb05ddbcb 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -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. @@ -164,13 +164,13 @@ impl BufWriter { /// assert_eq!(&buffered_data.unwrap(), b"ata"); /// ``` #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] - pub fn into_parts(mut self) -> (W, Result, 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, 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) } diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index ee0db30e22c2e..ab66deaf31d22 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -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(); +} From 4d35754c46b4e0183770f4d7272b0e70a6553b19 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 12 Jul 2024 17:36:21 -0700 Subject: [PATCH 29/33] Add URL and crate_name to test cases --- .../issue-100204-inline-impl-through-glob-import.rs | 1 + tests/rustdoc/issue-100241.rs | 2 ++ tests/rustdoc/issue-100620.rs | 2 ++ tests/rustdoc/issue-102154.rs | 2 ++ tests/rustdoc/issue-105735-overlapping-reexport-2.rs | 1 + tests/rustdoc/issue-105735-overlapping-reexport.rs | 1 + tests/rustdoc/issue-105952.rs | 1 + tests/rustdoc/issue-106142.rs | 7 +++++-- tests/rustdoc/issue-106421-not-internal.rs | 5 ++++- tests/rustdoc/issue-106421.rs | 4 +++- .../issue-99221-multiple-macro-rules-w-same-name.rs | 1 + tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs | 1 + tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs | 1 + tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs | 1 + 14 files changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs b/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs index 7f05e57ec09b0..ba6ed4278716f 100644 --- a/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs +++ b/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs @@ -2,6 +2,7 @@ //@ build-aux-docs //@ ignore-cross-compile +// https://github.com/rust-lang/rust/issues/100204 #![crate_name="second"] extern crate first; diff --git a/tests/rustdoc/issue-100241.rs b/tests/rustdoc/issue-100241.rs index e4c613dd2791e..eef4b8355bfd7 100644 --- a/tests/rustdoc/issue-100241.rs +++ b/tests/rustdoc/issue-100241.rs @@ -3,6 +3,8 @@ // Check that this isn't an ICE //@ should-fail +// https://github.com/rust-lang/rust/issues/100241 + mod foo { pub use inner::S; //~^ ERROR unresolved imports `inner`, `foo::S` diff --git a/tests/rustdoc/issue-100620.rs b/tests/rustdoc/issue-100620.rs index 097666eb515d1..39d70bab29e4a 100644 --- a/tests/rustdoc/issue-100620.rs +++ b/tests/rustdoc/issue-100620.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/100620 + pub trait Bar {} pub trait Qux {} diff --git a/tests/rustdoc/issue-102154.rs b/tests/rustdoc/issue-102154.rs index b36f270806ff3..58cabe769272b 100644 --- a/tests/rustdoc/issue-102154.rs +++ b/tests/rustdoc/issue-102154.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/102154 + trait A { type B; } diff --git a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs index 946184c5a0476..9f823ec5923cd 100644 --- a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs +++ b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs @@ -1,4 +1,5 @@ // Regression test to ensure that both `AtomicU8` items are displayed but not the re-export. +// https://github.com/rust-lang/rust/issues/105735 #![crate_name = "foo"] #![no_std] diff --git a/tests/rustdoc/issue-105735-overlapping-reexport.rs b/tests/rustdoc/issue-105735-overlapping-reexport.rs index 0fd17fd9577c2..2a2d0fa98309e 100644 --- a/tests/rustdoc/issue-105735-overlapping-reexport.rs +++ b/tests/rustdoc/issue-105735-overlapping-reexport.rs @@ -1,4 +1,5 @@ // Regression test to ensure that both `AtomicU8` items are displayed but not the re-export. +// https://github.com/rust-lang/rust/issues/105735 #![crate_name = "foo"] #![no_std] diff --git a/tests/rustdoc/issue-105952.rs b/tests/rustdoc/issue-105952.rs index 173efb82f4b98..1bcdfac734290 100644 --- a/tests/rustdoc/issue-105952.rs +++ b/tests/rustdoc/issue-105952.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/105952 #![crate_name = "foo"] #![feature(associated_const_equality)] diff --git a/tests/rustdoc/issue-106142.rs b/tests/rustdoc/issue-106142.rs index 52adc5dbbf1a1..0d146a3c5cd0c 100644 --- a/tests/rustdoc/issue-106142.rs +++ b/tests/rustdoc/issue-106142.rs @@ -1,5 +1,8 @@ -//@ has 'issue_106142/a/index.html' -//@ count 'issue_106142/a/index.html' '//ul[@class="item-table"]//li//a' 1 +// https://github.com/rust-lang/rust/issues/106142 +#![crate_name="foo"] + +//@ has 'foo/a/index.html' +//@ count 'foo/a/index.html' '//ul[@class="item-table"]//li//a' 1 #![allow(rustdoc::broken_intra_doc_links)] diff --git a/tests/rustdoc/issue-106421-not-internal.rs b/tests/rustdoc/issue-106421-not-internal.rs index f328a1036ebe9..a85cfa78cdcda 100644 --- a/tests/rustdoc/issue-106421-not-internal.rs +++ b/tests/rustdoc/issue-106421-not-internal.rs @@ -2,7 +2,10 @@ //@ ignore-cross-compile // This is the version where a non-compiler-internal crate inlines a compiler-internal one. // In this case, the item shouldn't be documented, because regular users can't get at it. +// https://github.com/rust-lang/rust/issues/106421 +#![crate_name="bar"] + extern crate foo; -//@ !has issue_106421_not_internal/struct.FatalError.html '//*[@id="method.raise"]' 'fn raise' +//@ !has bar/struct.FatalError.html '//*[@id="method.raise"]' 'fn raise' pub use foo::FatalError; diff --git a/tests/rustdoc/issue-106421.rs b/tests/rustdoc/issue-106421.rs index c2064c7109078..aa88a569aef2f 100644 --- a/tests/rustdoc/issue-106421.rs +++ b/tests/rustdoc/issue-106421.rs @@ -1,8 +1,10 @@ //@ aux-build:issue-106421-force-unstable.rs //@ ignore-cross-compile //@ compile-flags: -Zforce-unstable-if-unmarked +// https://github.com/rust-lang/rust/issues/106421 +#![crate_name="bar"] extern crate foo; -//@ has issue_106421/struct.FatalError.html '//*[@id="method.raise"]' 'fn raise' +//@ has bar/struct.FatalError.html '//*[@id="method.raise"]' 'fn raise' pub use foo::FatalError; diff --git a/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs b/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs index e7fb4fb3f0ea3..4a1798a849691 100644 --- a/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs +++ b/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs @@ -2,6 +2,7 @@ //@ build-aux-docs //@ ignore-cross-compile +// https://github.com/rust-lang/rust/issues/99221 #![crate_name = "foo"] #[macro_use] diff --git a/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs b/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs index 8758342fe0736..4c2f77fec23d7 100644 --- a/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs +++ b/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs @@ -2,6 +2,7 @@ //@ build-aux-docs //@ ignore-cross-compile +// https://github.com/rust-lang/rust/issues/99221 #![crate_name = "foo"] #[macro_use] diff --git a/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs b/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs index d7c4f1db320c7..60a2aa388ee10 100644 --- a/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs +++ b/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs @@ -2,6 +2,7 @@ //@ build-aux-docs //@ ignore-cross-compile +// https://github.com/rust-lang/rust/issues/99734 #![crate_name = "foo"] #[macro_use] diff --git a/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs b/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs index 627cfc0b80b3f..d48464c478f38 100644 --- a/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs +++ b/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs @@ -2,6 +2,7 @@ //@ build-aux-docs //@ ignore-cross-compile +// https://github.com/rust-lang/rust/issues/99734 #![crate_name = "foo"] #[macro_use] From 17419f6499546443fd311cc81a0d44ae233c306f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 12 Jul 2024 18:12:32 -0700 Subject: [PATCH 30/33] rustdoc: rename `issue-\d+.rs` tests to have meaningful names --- tests/rustdoc/{issue-108281.rs => attributes-inlining-108281.rs} | 0 tests/rustdoc/{issue-101743-bold-tag.rs => bold-tag-101743.rs} | 0 ...ernal.rs => force-unstable-if-unmarked-106421-not-internal.rs} | 0 .../{issue-106421.rs => force-unstable-if-unmarked-106421.rs} | 0 tests/rustdoc/{issue-102154.rs => ice-assoc-type-loop-102154.rs} | 0 .../{issue-105952.rs => ice-associated-const-equality-105952.rs} | 0 tests/rustdoc/{issue-107995.rs => ice-intra-doc-links-107995.rs} | 0 ...issue-100620.rs => ice-method-where-clause-circular-100620.rs} | 0 .../rustdoc/{issue-100241.rs => ice-unresolved-import-100241.rs} | 0 ...h-glob-import.rs => inline-impl-through-glob-import-100204.rs} | 0 .../{issue-108231.rs => macro-export-crate-root-108231.rs} | 0 .../{issue-106142.rs => macro-rules-broken-intra-doc-106142.rs} | 0 ...igns-w-same-name.rs => multiple-foreigns-w-same-name-99734.rs} | 0 ...s-w-same-name.rs => multiple-macro-rules-w-same-name-99221.rs} | 0 ...ple-mods-w-same-name.rs => multiple-mods-w-same-name-99734.rs} | 0 ...ructs-w-same-name.rs => multiple-structs-w-same-name-99221.rs} | 0 ...overlapping-reexport-2.rs => overlapping-reexport-105735-2.rs} | 0 ...735-overlapping-reexport.rs => overlapping-reexport-105735.rs} | 0 tests/rustdoc/{issue-107350.rs => pub-use-loop-107350.rs} | 0 ...679-reexport-of-reexport.rs => reexport-of-reexport-108679.rs} | 0 20 files changed, 0 insertions(+), 0 deletions(-) rename tests/rustdoc/{issue-108281.rs => attributes-inlining-108281.rs} (100%) rename tests/rustdoc/{issue-101743-bold-tag.rs => bold-tag-101743.rs} (100%) rename tests/rustdoc/{issue-106421-not-internal.rs => force-unstable-if-unmarked-106421-not-internal.rs} (100%) rename tests/rustdoc/{issue-106421.rs => force-unstable-if-unmarked-106421.rs} (100%) rename tests/rustdoc/{issue-102154.rs => ice-assoc-type-loop-102154.rs} (100%) rename tests/rustdoc/{issue-105952.rs => ice-associated-const-equality-105952.rs} (100%) rename tests/rustdoc/{issue-107995.rs => ice-intra-doc-links-107995.rs} (100%) rename tests/rustdoc/{issue-100620.rs => ice-method-where-clause-circular-100620.rs} (100%) rename tests/rustdoc/{issue-100241.rs => ice-unresolved-import-100241.rs} (100%) rename tests/rustdoc/{issue-100204-inline-impl-through-glob-import.rs => inline-impl-through-glob-import-100204.rs} (100%) rename tests/rustdoc/{issue-108231.rs => macro-export-crate-root-108231.rs} (100%) rename tests/rustdoc/{issue-106142.rs => macro-rules-broken-intra-doc-106142.rs} (100%) rename tests/rustdoc/{issue-99734-multiple-foreigns-w-same-name.rs => multiple-foreigns-w-same-name-99734.rs} (100%) rename tests/rustdoc/{issue-99221-multiple-macro-rules-w-same-name.rs => multiple-macro-rules-w-same-name-99221.rs} (100%) rename tests/rustdoc/{issue-99734-multiple-mods-w-same-name.rs => multiple-mods-w-same-name-99734.rs} (100%) rename tests/rustdoc/{issue-99221-multiple-structs-w-same-name.rs => multiple-structs-w-same-name-99221.rs} (100%) rename tests/rustdoc/{issue-105735-overlapping-reexport-2.rs => overlapping-reexport-105735-2.rs} (100%) rename tests/rustdoc/{issue-105735-overlapping-reexport.rs => overlapping-reexport-105735.rs} (100%) rename tests/rustdoc/{issue-107350.rs => pub-use-loop-107350.rs} (100%) rename tests/rustdoc/{issue-108679-reexport-of-reexport.rs => reexport-of-reexport-108679.rs} (100%) diff --git a/tests/rustdoc/issue-108281.rs b/tests/rustdoc/attributes-inlining-108281.rs similarity index 100% rename from tests/rustdoc/issue-108281.rs rename to tests/rustdoc/attributes-inlining-108281.rs diff --git a/tests/rustdoc/issue-101743-bold-tag.rs b/tests/rustdoc/bold-tag-101743.rs similarity index 100% rename from tests/rustdoc/issue-101743-bold-tag.rs rename to tests/rustdoc/bold-tag-101743.rs diff --git a/tests/rustdoc/issue-106421-not-internal.rs b/tests/rustdoc/force-unstable-if-unmarked-106421-not-internal.rs similarity index 100% rename from tests/rustdoc/issue-106421-not-internal.rs rename to tests/rustdoc/force-unstable-if-unmarked-106421-not-internal.rs diff --git a/tests/rustdoc/issue-106421.rs b/tests/rustdoc/force-unstable-if-unmarked-106421.rs similarity index 100% rename from tests/rustdoc/issue-106421.rs rename to tests/rustdoc/force-unstable-if-unmarked-106421.rs diff --git a/tests/rustdoc/issue-102154.rs b/tests/rustdoc/ice-assoc-type-loop-102154.rs similarity index 100% rename from tests/rustdoc/issue-102154.rs rename to tests/rustdoc/ice-assoc-type-loop-102154.rs diff --git a/tests/rustdoc/issue-105952.rs b/tests/rustdoc/ice-associated-const-equality-105952.rs similarity index 100% rename from tests/rustdoc/issue-105952.rs rename to tests/rustdoc/ice-associated-const-equality-105952.rs diff --git a/tests/rustdoc/issue-107995.rs b/tests/rustdoc/ice-intra-doc-links-107995.rs similarity index 100% rename from tests/rustdoc/issue-107995.rs rename to tests/rustdoc/ice-intra-doc-links-107995.rs diff --git a/tests/rustdoc/issue-100620.rs b/tests/rustdoc/ice-method-where-clause-circular-100620.rs similarity index 100% rename from tests/rustdoc/issue-100620.rs rename to tests/rustdoc/ice-method-where-clause-circular-100620.rs diff --git a/tests/rustdoc/issue-100241.rs b/tests/rustdoc/ice-unresolved-import-100241.rs similarity index 100% rename from tests/rustdoc/issue-100241.rs rename to tests/rustdoc/ice-unresolved-import-100241.rs diff --git a/tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs b/tests/rustdoc/inline-impl-through-glob-import-100204.rs similarity index 100% rename from tests/rustdoc/issue-100204-inline-impl-through-glob-import.rs rename to tests/rustdoc/inline-impl-through-glob-import-100204.rs diff --git a/tests/rustdoc/issue-108231.rs b/tests/rustdoc/macro-export-crate-root-108231.rs similarity index 100% rename from tests/rustdoc/issue-108231.rs rename to tests/rustdoc/macro-export-crate-root-108231.rs diff --git a/tests/rustdoc/issue-106142.rs b/tests/rustdoc/macro-rules-broken-intra-doc-106142.rs similarity index 100% rename from tests/rustdoc/issue-106142.rs rename to tests/rustdoc/macro-rules-broken-intra-doc-106142.rs diff --git a/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs b/tests/rustdoc/multiple-foreigns-w-same-name-99734.rs similarity index 100% rename from tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs rename to tests/rustdoc/multiple-foreigns-w-same-name-99734.rs diff --git a/tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs b/tests/rustdoc/multiple-macro-rules-w-same-name-99221.rs similarity index 100% rename from tests/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs rename to tests/rustdoc/multiple-macro-rules-w-same-name-99221.rs diff --git a/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs b/tests/rustdoc/multiple-mods-w-same-name-99734.rs similarity index 100% rename from tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs rename to tests/rustdoc/multiple-mods-w-same-name-99734.rs diff --git a/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs b/tests/rustdoc/multiple-structs-w-same-name-99221.rs similarity index 100% rename from tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs rename to tests/rustdoc/multiple-structs-w-same-name-99221.rs diff --git a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs b/tests/rustdoc/overlapping-reexport-105735-2.rs similarity index 100% rename from tests/rustdoc/issue-105735-overlapping-reexport-2.rs rename to tests/rustdoc/overlapping-reexport-105735-2.rs diff --git a/tests/rustdoc/issue-105735-overlapping-reexport.rs b/tests/rustdoc/overlapping-reexport-105735.rs similarity index 100% rename from tests/rustdoc/issue-105735-overlapping-reexport.rs rename to tests/rustdoc/overlapping-reexport-105735.rs diff --git a/tests/rustdoc/issue-107350.rs b/tests/rustdoc/pub-use-loop-107350.rs similarity index 100% rename from tests/rustdoc/issue-107350.rs rename to tests/rustdoc/pub-use-loop-107350.rs diff --git a/tests/rustdoc/issue-108679-reexport-of-reexport.rs b/tests/rustdoc/reexport-of-reexport-108679.rs similarity index 100% rename from tests/rustdoc/issue-108679-reexport-of-reexport.rs rename to tests/rustdoc/reexport-of-reexport-108679.rs From 42ee400b0ffa7eeffb51e5b1e2e3fbcc6a130e0c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 12 Jul 2024 18:16:30 -0700 Subject: [PATCH 31/33] Move assertion-free rustdoc ice tests to rustdoc-ui --- tests/{rustdoc => rustdoc-ui}/ice-assoc-type-loop-102154.rs | 1 + .../ice-method-where-clause-circular-100620.rs | 1 + tests/{rustdoc => rustdoc-ui}/ice-unresolved-import-100241.rs | 0 3 files changed, 2 insertions(+) rename tests/{rustdoc => rustdoc-ui}/ice-assoc-type-loop-102154.rs (94%) rename tests/{rustdoc => rustdoc-ui}/ice-method-where-clause-circular-100620.rs (95%) rename tests/{rustdoc => rustdoc-ui}/ice-unresolved-import-100241.rs (100%) diff --git a/tests/rustdoc/ice-assoc-type-loop-102154.rs b/tests/rustdoc-ui/ice-assoc-type-loop-102154.rs similarity index 94% rename from tests/rustdoc/ice-assoc-type-loop-102154.rs rename to tests/rustdoc-ui/ice-assoc-type-loop-102154.rs index 58cabe769272b..68e22ce6ea154 100644 --- a/tests/rustdoc/ice-assoc-type-loop-102154.rs +++ b/tests/rustdoc-ui/ice-assoc-type-loop-102154.rs @@ -1,3 +1,4 @@ +//@ check-pass // https://github.com/rust-lang/rust/issues/102154 trait A { diff --git a/tests/rustdoc/ice-method-where-clause-circular-100620.rs b/tests/rustdoc-ui/ice-method-where-clause-circular-100620.rs similarity index 95% rename from tests/rustdoc/ice-method-where-clause-circular-100620.rs rename to tests/rustdoc-ui/ice-method-where-clause-circular-100620.rs index 39d70bab29e4a..e12b214410bc2 100644 --- a/tests/rustdoc/ice-method-where-clause-circular-100620.rs +++ b/tests/rustdoc-ui/ice-method-where-clause-circular-100620.rs @@ -1,3 +1,4 @@ +//@ check-pass // https://github.com/rust-lang/rust/issues/100620 pub trait Bar {} diff --git a/tests/rustdoc/ice-unresolved-import-100241.rs b/tests/rustdoc-ui/ice-unresolved-import-100241.rs similarity index 100% rename from tests/rustdoc/ice-unresolved-import-100241.rs rename to tests/rustdoc-ui/ice-unresolved-import-100241.rs From fc0d1dc99bc579b07ad59733d74e9ec6e823d6e9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 13 Jul 2024 10:04:33 +0300 Subject: [PATCH 32/33] use `ModeToolBootstrap` for run-make-support's crate tests We don't need to ensure std (and rustc) for testing run-make-support's unit tests. Using stage 0 compiler is already enough and speeds up `x test run-make-support` invocations on a clean build. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 0b60587bb792b..33517c5e2e440 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1325,13 +1325,12 @@ impl Step for CrateRunMakeSupport { /// Runs `cargo test` for run-make-support. fn run(self, builder: &Builder<'_>) { let host = self.host; - let compiler = builder.compiler(builder.top_stage, host); + let compiler = builder.compiler(0, host); - builder.ensure(compile::Std::new(compiler, host)); let mut cargo = tool::prepare_tool_cargo( builder, compiler, - Mode::ToolStd, + Mode::ToolBootstrap, host, "test", "src/tools/run-make-support", From 41070bd9381bc0604171eba9308869eecd94b20b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 13 Jul 2024 19:58:36 +0300 Subject: [PATCH 33/33] explain why we use in-tree std for compiletest Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 33517c5e2e440..1fa58040a1195 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -686,6 +686,8 @@ impl Step for CompiletestTest { let mut cargo = tool::prepare_tool_cargo( builder, compiler, + // compiletest uses libtest internals; make it use the in-tree std to make sure it never breaks + // when std sources change. Mode::ToolStd, host, "test",