From 967c0ad5879f95c3663a1a0c7f02b2038f7eadb9 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Wed, 19 Jan 2022 16:44:13 +0100 Subject: [PATCH 01/19] Implement `IterMut::as_mut_slice` --- library/core/src/slice/iter.rs | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index ad1d6b8b846a0..2821109cd89f9 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -304,6 +304,47 @@ impl<'a, T> IterMut<'a, T> { pub fn as_slice(&self) -> &[T] { self.make_slice() } + + /// Views the underlying data as a mutable subslice of the original data. + /// + /// To avoid creating `&mut [T]` references that alias, the returned slice + /// borrows its lifetime from the iterator the method is applied on. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(slice_iter_mut_as_mut_slice)] + /// + /// let mut slice: &mut [usize] = &mut [1, 2, 3]; + /// + /// // First, we get the iterator: + /// let mut iter = slice.iter_mut(); + /// // Then, we get a mutable slice from it: + /// let mut_slice = iter.as_mut_slice(); + /// // So if we check what the `as_mut_slice` method returned, we have "[1, 2, 3]": + /// assert_eq!(mut_slice, &mut [1, 2, 3]); + /// + /// // We can use it to mutate the slice: + /// mut_slice[0] = 4; + /// mut_slice[2] = 5; + /// + /// // Next, we can move to the second element of the slice, checking that + /// // it yields the value we just wrote: + /// assert_eq!(iter.next(), Some(&mut 4)); + /// // Now `as_mut_slice` returns "[2, 5]": + /// assert_eq!(iter.as_mut_slice(), &mut [2, 5]); + /// ``` + #[must_use] + // FIXME: Uncomment the `AsMut<[T]>` impl when this gets stabilized. + #[unstable(feature = "slice_iter_mut_as_mut_slice", issue = "93079")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: the iterator was created from a mutable slice with pointer + // `self.ptr` and length `len!(self)`. This guarantees that all the prerequisites + // for `from_raw_parts_mut` are fulfilled. + unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) } + } } #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] @@ -313,6 +354,13 @@ impl AsRef<[T]> for IterMut<'_, T> { } } +// #[stable(feature = "slice_iter_mut_as_mut_slice", since = "FIXME")] +// impl AsMut<[T]> for IterMut<'_, T> { +// fn as_mut(&mut self) -> &mut [T] { +// self.as_mut_slice() +// } +// } + iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}} /// An internal abstraction over the splitting iterators, so that From a23e7513fa530d9013ca2dd67ad0e0ffb16aa16f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 11 Mar 2022 17:25:04 +0100 Subject: [PATCH 02/19] Panic when advance_slices()'ing too far. --- library/std/src/io/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 3fa965d08e698..47be2c504edd9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1155,7 +1155,9 @@ impl<'a> IoSliceMut<'a> { } *bufs = &mut replace(bufs, &mut [])[remove..]; - if !bufs.is_empty() { + if bufs.is_empty() { + assert!(n == accumulated_len, "advancing io slices beyond their length"); + } else { bufs[0].advance(n - accumulated_len) } } @@ -1289,7 +1291,9 @@ impl<'a> IoSlice<'a> { } *bufs = &mut replace(bufs, &mut [])[remove..]; - if !bufs.is_empty() { + if bufs.is_empty() { + assert!(n == accumulated_len, "advancing io slices beyond their length"); + } else { bufs[0].advance(n - accumulated_len) } } From 4d7daa07b12fd60b4caa9d4af4baf7ead3c21de8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 11 Mar 2022 17:25:19 +0100 Subject: [PATCH 03/19] Update advance and advance_slices docs. --- library/std/src/io/mod.rs | 42 ++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 47be2c504edd9..5bb178fc441f3 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1085,6 +1085,10 @@ impl<'a> IoSliceMut<'a> { /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of /// multiple buffers. /// + /// # Panics + /// + /// Panics when trying to advance beyond the end of the slice. + /// /// # Examples /// /// ``` @@ -1106,15 +1110,18 @@ impl<'a> IoSliceMut<'a> { self.0.advance(n) } - /// Advance the internal cursor of the slices. + /// Advance a slice of slices. /// - /// # Notes + /// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over. + /// If the cursor ends up in the middle of an `IoSliceMut`, it is modified + /// to start at that cursor. + /// + /// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes, + /// the result will only include the second `IoSliceMut`, advanced by 2 bytes. + /// + /// # Panics /// - /// Elements in the slice may be modified if the cursor is not advanced to - /// the end of the slice. For example if we have a slice of buffers with 2 - /// `IoSliceMut`s, both of length 8, and we advance the cursor by 10 bytes - /// the first `IoSliceMut` will be untouched however the second will be - /// modified to remove the first 2 bytes (10 - 8). + /// Panics when trying to advance beyond the end of the slices. /// /// # Examples /// @@ -1222,6 +1229,10 @@ impl<'a> IoSlice<'a> { /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple /// buffers. /// + /// # Panics + /// + /// Panics when trying to advance beyond the end of the slice. + /// /// # Examples /// /// ``` @@ -1243,15 +1254,18 @@ impl<'a> IoSlice<'a> { self.0.advance(n) } - /// Advance the internal cursor of the slices. + /// Advance a slice of slices. /// - /// # Notes + /// Shrinks the slice to remove any `IoSlice`s that are fully advanced over. + /// If the cursor ends up in the middle of an `IoSlice`, it is modified + /// to start at that cursor. + /// + /// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes, + /// the result will only include the second `IoSlice`, advanced by 2 bytes. + /// + /// # Panics /// - /// Elements in the slice may be modified if the cursor is not advanced to - /// the end of the slice. For example if we have a slice of buffers with 2 - /// `IoSlice`s, both of length 8, and we advance the cursor by 10 bytes the - /// first `IoSlice` will be untouched however the second will be modified to - /// remove the first 2 bytes (10 - 8). + /// Panics when trying to advance beyond the end of the slices. /// /// # Examples /// From 1890372c9e64d1fb5ee45bbb2d785510a6011e70 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 11 Mar 2022 17:38:29 +0100 Subject: [PATCH 04/19] Update tests. --- library/std/src/io/tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index eb62634856462..d5a8c93b0ce9f 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -423,18 +423,18 @@ fn io_slice_mut_advance_slices() { } #[test] +#[should_panic] fn io_slice_mut_advance_slices_empty_slice() { let mut empty_bufs = &mut [][..]; - // Shouldn't panic. IoSliceMut::advance_slices(&mut empty_bufs, 1); } #[test] +#[should_panic] fn io_slice_mut_advance_slices_beyond_total_length() { let mut buf1 = [1; 8]; let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..]; - // Going beyond the total length should be ok. IoSliceMut::advance_slices(&mut bufs, 9); assert!(bufs.is_empty()); } @@ -463,18 +463,18 @@ fn io_slice_advance_slices() { } #[test] +#[should_panic] fn io_slice_advance_slices_empty_slice() { let mut empty_bufs = &mut [][..]; - // Shouldn't panic. IoSlice::advance_slices(&mut empty_bufs, 1); } #[test] +#[should_panic] fn io_slice_advance_slices_beyond_total_length() { let buf1 = [1; 8]; let mut bufs = &mut [IoSlice::new(&buf1)][..]; - // Going beyond the total length should be ok. IoSlice::advance_slices(&mut bufs, 9); assert!(bufs.is_empty()); } From 1ac54401d1b7224f1b8744b2b1f130d4d3cdfe34 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Sun, 1 May 2022 15:12:20 -0400 Subject: [PATCH 05/19] add `{Arc, Rc}::downcast_unchecked` --- library/alloc/src/rc.rs | 40 ++++++++++++++++++++++++++++++++-- library/alloc/src/sync.rs | 45 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3065169e5e2cb..47808d5f86ac7 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1241,8 +1241,6 @@ impl Rc { } impl Rc { - #[inline] - #[stable(feature = "rc_downcast", since = "1.29.0")] /// Attempt to downcast the `Rc` to a concrete type. /// /// # Examples @@ -1261,6 +1259,8 @@ impl Rc { /// print_if_string(Rc::new(my_string)); /// print_if_string(Rc::new(0i8)); /// ``` + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] pub fn downcast(self) -> Result, Rc> { if (*self).is::() { unsafe { @@ -1272,6 +1272,42 @@ impl Rc { Err(self) } } + + /// Downcasts the `Rc` to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// use std::rc::Rc; + /// + /// let x: Rc = Rc::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Rc { + unsafe { + let ptr = self.ptr.cast::>(); + mem::forget(self); + Rc::from_inner(ptr) + } + } } impl Rc { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 7e7670aad6425..2d9c7ff4f6b48 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1691,8 +1691,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { } impl Arc { - #[inline] - #[stable(feature = "rc_downcast", since = "1.29.0")] /// Attempt to downcast the `Arc` to a concrete type. /// /// # Examples @@ -1711,9 +1709,11 @@ impl Arc { /// print_if_string(Arc::new(my_string)); /// print_if_string(Arc::new(0i8)); /// ``` + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] pub fn downcast(self) -> Result, Self> where - T: Any + Send + Sync + 'static, + T: Any + Send + Sync, { if (*self).is::() { unsafe { @@ -1725,6 +1725,45 @@ impl Arc { Err(self) } } + + /// Downcasts the `Arc` to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Arc + where + T: Any + Send + Sync, + { + unsafe { + let ptr = self.ptr.cast::>(); + mem::forget(self); + Arc::from_inner(ptr) + } + } } impl Weak { From 6d523e9a75fe55eae708d6e606a492f9c891af34 Mon Sep 17 00:00:00 2001 From: mbartlett21 <29034492+mbartlett21@users.noreply.github.com> Date: Thu, 5 May 2022 09:58:13 +1000 Subject: [PATCH 06/19] Fix the generator example for `pin!()` --- library/core/src/pin.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 720317b05e080..ccef35b45325a 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1006,9 +1006,10 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// // Allow generator to be self-referential (not `Unpin`) /// // vvvvvv so that locals can cross yield points. /// static || { -/// let foo = String::from("foo"); // --+ -/// yield 0; // | <- crosses yield point! -/// println!("{}", &foo); // <----------+ +/// let foo = String::from("foo"); +/// let foo_ref = &foo; // ------+ +/// yield 0; // | <- crosses yield point! +/// println!("{foo_ref}"); // <--+ /// yield foo.len(); /// } /// } From 5ae95fa89a87a643ec74d5c164246146c8188228 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 7 Jun 2022 09:36:34 -0700 Subject: [PATCH 07/19] Document Rust's stance on `/proc/self/mem` Add documentation to `std::os::unix::io` describing Rust's stance on `/proc/self/mem`, treating it as an external entity which is outside the scope of Rust's safety guarantees. --- library/std/src/os/unix/io/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 0fd9591b0165a..d2c5f74132458 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -44,6 +44,26 @@ //! Like boxes, `OwnedFd` values conceptually own the resource they point to, //! and free (close) it when they are dropped. //! +//! ## What about `/proc/self/mem` and similar OS features? +//! +//! Some platforms have a feature known as `/proc/self/mem`, which is a +//! filesystem path that can be opened, producing a file descriptor that, when +//! read from or written to, reads and writes the process's memory. These reads +//! and writes happen outside the control of the Rust compiler, so they do not +//! uphold Rust's memory safety guarantees. +//! +//! Does this mean that all APIs that might allow `/proc/self/mem` to be opened +//! and read from or written to must be `unsafe`? No. Rust's safety guarantees +//! only cover what the program itself can do, and not what entities outside +//! the program can do to it. `/proc/self/mem` is considered to be such an +//! external entity, along with debugggers and people with physical access to +//! the hardware. This is true even in cases where the program is controling +//! the external entity. +//! +//! If you desire to comprehensively prevent programs from reaching out and +//! causing external entities to reach back in and violate memory safety, it's +//! necessary to use *sandboxing*, which is outside the scope of `std`. +//! //! [`BorrowedFd<'a>`]: crate::os::unix::io::BorrowedFd #![stable(feature = "rust1", since = "1.0.0")] From fbb59e706287525a9157edc65944030f9cd251fd Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 7 Jun 2022 09:53:26 -0700 Subject: [PATCH 08/19] Update library/std/src/os/unix/io/mod.rs Co-authored-by: Sean Stangl --- library/std/src/os/unix/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index d2c5f74132458..73cb3d31a7b00 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -56,7 +56,7 @@ //! and read from or written to must be `unsafe`? No. Rust's safety guarantees //! only cover what the program itself can do, and not what entities outside //! the program can do to it. `/proc/self/mem` is considered to be such an -//! external entity, along with debugggers and people with physical access to +//! external entity, along with debuggers and people with physical access to //! the hardware. This is true even in cases where the program is controling //! the external entity. //! From 52cb18b664fe594bfac03aaf5b3fb84986d74f02 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 7 Jun 2022 09:53:34 -0700 Subject: [PATCH 09/19] Update library/std/src/os/unix/io/mod.rs Co-authored-by: Sean Stangl --- library/std/src/os/unix/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 73cb3d31a7b00..139accf3f8d4d 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -57,7 +57,7 @@ //! only cover what the program itself can do, and not what entities outside //! the program can do to it. `/proc/self/mem` is considered to be such an //! external entity, along with debuggers and people with physical access to -//! the hardware. This is true even in cases where the program is controling +//! the hardware. This is true even in cases where the program is controlling //! the external entity. //! //! If you desire to comprehensively prevent programs from reaching out and From 27d9ab447b4a7b92565d1c2be9e45f58f0243731 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 7 Jun 2022 10:38:31 -0700 Subject: [PATCH 10/19] Update library/std/src/os/unix/io/mod.rs Co-authored-by: Josh Triplett --- library/std/src/os/unix/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 139accf3f8d4d..610a5da77781d 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -46,7 +46,7 @@ //! //! ## What about `/proc/self/mem` and similar OS features? //! -//! Some platforms have a feature known as `/proc/self/mem`, which is a +//! Some platforms have special files, such as `/proc/self/mem`, which is a //! filesystem path that can be opened, producing a file descriptor that, when //! read from or written to, reads and writes the process's memory. These reads //! and writes happen outside the control of the Rust compiler, so they do not From f9662f2c18208727706c41848715b7400c9e4fe0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 7 Jun 2022 11:16:32 -0700 Subject: [PATCH 11/19] Update library/std/src/os/unix/io/mod.rs Co-authored-by: Josh Triplett --- library/std/src/os/unix/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 610a5da77781d..bc2f6b7659ff7 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -56,7 +56,7 @@ //! and read from or written to must be `unsafe`? No. Rust's safety guarantees //! only cover what the program itself can do, and not what entities outside //! the program can do to it. `/proc/self/mem` is considered to be such an -//! external entity, along with debuggers and people with physical access to +//! external entity, along with debugging interfaces, and people with physical access to //! the hardware. This is true even in cases where the program is controlling //! the external entity. //! From 7656e085e3d056f0f0f35a9112727478a848350f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 8 Jun 2022 08:24:28 -0700 Subject: [PATCH 12/19] Reword a question into a statement. --- library/std/src/os/unix/io/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index bc2f6b7659ff7..8935f303081ca 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -52,8 +52,8 @@ //! and writes happen outside the control of the Rust compiler, so they do not //! uphold Rust's memory safety guarantees. //! -//! Does this mean that all APIs that might allow `/proc/self/mem` to be opened -//! and read from or written to must be `unsafe`? No. Rust's safety guarantees +//! However, this does not mean that all APIs that might allow `/proc/self/mem` +//! to be opened and read from or written must be `unsafe`. Rust's safety guarantees //! only cover what the program itself can do, and not what entities outside //! the program can do to it. `/proc/self/mem` is considered to be such an //! external entity, along with debugging interfaces, and people with physical access to From e89ec68d5db9aa58b8170b351e730d45304c812b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 8 Jun 2022 08:26:56 -0700 Subject: [PATCH 13/19] Update library/std/src/os/unix/io/mod.rs Co-authored-by: Mara Bos --- library/std/src/os/unix/io/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 8935f303081ca..0a9c95fd409af 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -46,9 +46,8 @@ //! //! ## What about `/proc/self/mem` and similar OS features? //! -//! Some platforms have special files, such as `/proc/self/mem`, which is a -//! filesystem path that can be opened, producing a file descriptor that, when -//! read from or written to, reads and writes the process's memory. These reads +//! Some platforms have special files, such as `/proc/self/mem`, which +//! provide read and write access to the process's memory. Such reads //! and writes happen outside the control of the Rust compiler, so they do not //! uphold Rust's memory safety guarantees. //! From 158ff5cdd47b72d4ef9f04c4a3145c0b74bdba25 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 8 Jun 2022 08:27:32 -0700 Subject: [PATCH 14/19] Reword the question in the section header too. This adopts the wording suggested in https://github.com/rust-lang/rust/pull/97837#discussion_r892524129. --- library/std/src/os/unix/io/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 0a9c95fd409af..044cfb221b2f5 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -44,14 +44,14 @@ //! Like boxes, `OwnedFd` values conceptually own the resource they point to, //! and free (close) it when they are dropped. //! -//! ## What about `/proc/self/mem` and similar OS features? +//! ## `/proc/self/mem` and similar OS features //! //! Some platforms have special files, such as `/proc/self/mem`, which //! provide read and write access to the process's memory. Such reads //! and writes happen outside the control of the Rust compiler, so they do not //! uphold Rust's memory safety guarantees. //! -//! However, this does not mean that all APIs that might allow `/proc/self/mem` +//! This does not mean that all APIs that might allow `/proc/self/mem` //! to be opened and read from or written must be `unsafe`. Rust's safety guarantees //! only cover what the program itself can do, and not what entities outside //! the program can do to it. `/proc/self/mem` is considered to be such an From 69594414bfac4d0ae10da65ccffad6ab4b0fa05a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 8 Jun 2022 08:40:34 -0700 Subject: [PATCH 15/19] Fix trailing whitespace. --- library/std/src/os/unix/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 044cfb221b2f5..d1732fbfdfe60 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -46,7 +46,7 @@ //! //! ## `/proc/self/mem` and similar OS features //! -//! Some platforms have special files, such as `/proc/self/mem`, which +//! Some platforms have special files, such as `/proc/self/mem`, which //! provide read and write access to the process's memory. Such reads //! and writes happen outside the control of the Rust compiler, so they do not //! uphold Rust's memory safety guarantees. From f725b97014169475d38dfe278028f06bc634728e Mon Sep 17 00:00:00 2001 From: Preston From Date: Wed, 15 Jun 2022 22:44:07 -0600 Subject: [PATCH 16/19] Include ForeignItem when visiting types for WF check Addresses Issue 95665 by including `hir::Node::ForeignItem` as a valid type to visit in `diagnostic_hir_wf_check`. Fixes #95665 --- compiler/rustc_typeck/src/hir_wf_check.rs | 5 ++++- src/test/ui/wf/issue-95665.rs | 18 ++++++++++++++++++ src/test/ui/wf/issue-95665.stderr | 15 +++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/wf/issue-95665.rs create mode 100644 src/test/ui/wf/issue-95665.stderr diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index b4b438a561a21..4392b9aada978 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -1,7 +1,7 @@ use crate::collect::ItemCtxt; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::HirId; +use rustc_hir::{ForeignItem, ForeignItemKind, HirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::TraitEngine; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; @@ -141,6 +141,9 @@ fn diagnostic_hir_wf_check<'tcx>( ref item => bug!("Unexpected item {:?}", item), }, hir::Node::Field(field) => Some(field.ty), + hir::Node::ForeignItem(ForeignItem { + kind: ForeignItemKind::Static(ty, _), .. + }) => Some(*ty), ref node => bug!("Unexpected node {:?}", node), }, WellFormedLoc::Param { function: _, param_idx } => { diff --git a/src/test/ui/wf/issue-95665.rs b/src/test/ui/wf/issue-95665.rs new file mode 100644 index 0000000000000..67923cbb2d6b5 --- /dev/null +++ b/src/test/ui/wf/issue-95665.rs @@ -0,0 +1,18 @@ +// Regression test for the ICE described in #95665. +// Ensure that the expected error is output (and thus that there is no ICE) + +pub trait Trait: {} + +pub struct Struct { + member: T, +} + +// uncomment and bug goes away +// impl Trait for u8 {} + +extern "C" { + static VAR: Struct; + //~^ 14:17: 14:27: the trait bound `u8: Trait` is not satisfied [E0277] +} + +fn main() {} diff --git a/src/test/ui/wf/issue-95665.stderr b/src/test/ui/wf/issue-95665.stderr new file mode 100644 index 0000000000000..b1cda59a9165b --- /dev/null +++ b/src/test/ui/wf/issue-95665.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/issue-95665.rs:14:17 + | +LL | static VAR: Struct; + | ^^^^^^^^^^ the trait `Trait` is not implemented for `u8` + | +note: required by a bound in `Struct` + --> $DIR/issue-95665.rs:6:22 + | +LL | pub struct Struct { + | ^^^^^ required by this bound in `Struct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From c867529461427bfb38e5a17461495b6a451ee374 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 20 Jun 2022 10:00:55 +0200 Subject: [PATCH 17/19] Show #![feature] in example. --- library/core/src/slice/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 2821109cd89f9..7f9f3ab27081d 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -315,7 +315,7 @@ impl<'a, T> IterMut<'a, T> { /// Basic usage: /// /// ``` - /// # #![feature(slice_iter_mut_as_mut_slice)] + /// #![feature(slice_iter_mut_as_mut_slice)] /// /// let mut slice: &mut [usize] = &mut [1, 2, 3]; /// From 8b93147f7e1805a8910f0d593aacf87f539a1280 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 18 May 2022 20:14:29 +0100 Subject: [PATCH 18/19] `Stdio::make_pipe` --- library/std/src/process.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index e253f46406fb7..567a424d8f0bd 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1273,6 +1273,22 @@ impl Stdio { pub fn null() -> Stdio { Stdio(imp::Stdio::Null) } + + /// Returns `true` if this requires [`Command`] to create a new pipe. + /// + /// # Example + /// + /// ``` + /// #![feature(stdio_makes_pipe)] + /// use std::process::Stdio; + /// + /// let io = Stdio::piped(); + /// assert_eq!(io.makes_pipe(), true); + /// ``` + #[unstable(feature = "stdio_makes_pipe", issue = "98288")] + pub fn makes_pipe(&self) -> bool { + matches!(self.0, imp::Stdio::MakePipe) + } } impl FromInner for Stdio { From 740a54c69b1c426c2b08329ea278140eb0059d42 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 18 May 2022 19:52:10 +0100 Subject: [PATCH 19/19] Windows: `CommandExt::async_pipes` --- library/std/src/os/windows/process.rs | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 1c7e361c2a4a8..cf693618ac1f6 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -161,6 +161,37 @@ pub trait CommandExt: Sealed { /// `CommandLineToArgvW` escaping rules. #[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")] fn raw_arg>(&mut self, text_to_append_as_is: S) -> &mut process::Command; + + /// When [`process::Command`] creates pipes, request that our side is always async. + /// + /// By default [`process::Command`] may choose to use pipes where both ends + /// are opened for synchronous read or write operations. By using + /// `async_pipes(true)`, this behavior is overridden so that our side is + /// always async. + /// + /// This is important because if doing async I/O a pipe or a file has to be + /// opened for async access. + /// + /// The end of the pipe sent to the child process will always be synchronous + /// regardless of this option. + /// + /// # Example + /// + /// ``` + /// #![feature(windows_process_extensions_async_pipes)] + /// use std::os::windows::process::CommandExt; + /// use std::process::{Command, Stdio}; + /// + /// # let program = ""; + /// + /// Command::new(program) + /// .async_pipes(true) + /// .stdin(Stdio::piped()) + /// .stdout(Stdio::piped()) + /// .stderr(Stdio::piped()); + /// ``` + #[unstable(feature = "windows_process_extensions_async_pipes", issue = "98289")] + fn async_pipes(&mut self, always_async: bool) -> &mut process::Command; } #[stable(feature = "windows_process_extensions", since = "1.16.0")] @@ -179,6 +210,15 @@ impl CommandExt for process::Command { self.as_inner_mut().raw_arg(raw_text.as_ref()); self } + + fn async_pipes(&mut self, always_async: bool) -> &mut process::Command { + // FIXME: This currently has an intentional no-op implementation. + // For the time being our side of the pipes will always be async. + // Once the ecosystem has adjusted, we may then be able to start making + // use of synchronous pipes within the standard library. + let _ = always_async; + self + } } #[unstable(feature = "windows_process_extensions_main_thread_handle", issue = "96723")]