Skip to content

Commit

Permalink
Auto merge of rust-lang#98292 - Dylan-DPC:rollup-hueb8tm, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - rust-lang#93080 (Implement `core::slice::IterMut::as_mut_slice` and `impl<T> AsMut<[T]> for IterMut<'_, T>`)
 - rust-lang#94855 (Panic when advance_slices()'ing too far and update docs.)
 - rust-lang#96609 (Add `{Arc, Rc}::downcast_unchecked`)
 - rust-lang#96719 (Fix the generator example for `pin!()`)
 - rust-lang#97149 (Windows: `CommandExt::async_pipes`)
 - rust-lang#97150 (`Stdio::makes_pipe`)
 - rust-lang#97837 (Document Rust's stance on `/proc/self/mem`)
 - rust-lang#98159 (Include ForeignItem when visiting types for WF check)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 20, 2022
2 parents 1d60108 + 7bde23b commit b12708f
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 29 deletions.
5 changes: 4 additions & 1 deletion compiler/rustc_typeck/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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 } => {
Expand Down
40 changes: 38 additions & 2 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,6 @@ impl<T: Clone> Rc<T> {
}

impl Rc<dyn Any> {
#[inline]
#[stable(feature = "rc_downcast", since = "1.29.0")]
/// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
///
/// # Examples
Expand All @@ -1274,6 +1272,8 @@ impl Rc<dyn Any> {
/// 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<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>> {
if (*self).is::<T>() {
unsafe {
Expand All @@ -1285,6 +1285,42 @@ impl Rc<dyn Any> {
Err(self)
}
}

/// Downcasts the `Rc<dyn Any>` 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<dyn Any> = Rc::new(1_usize);
///
/// unsafe {
/// assert_eq!(*x.downcast_unchecked::<usize>(), 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<T: Any>(self) -> Rc<T> {
unsafe {
let ptr = self.ptr.cast::<RcBox<T>>();
mem::forget(self);
Rc::from_inner(ptr)
}
}
}

impl<T: ?Sized> Rc<T> {
Expand Down
45 changes: 42 additions & 3 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1705,8 +1705,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
}

impl Arc<dyn Any + Send + Sync> {
#[inline]
#[stable(feature = "rc_downcast", since = "1.29.0")]
/// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
///
/// # Examples
Expand All @@ -1725,9 +1723,11 @@ impl Arc<dyn Any + Send + Sync> {
/// 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<T>(self) -> Result<Arc<T>, Self>
where
T: Any + Send + Sync + 'static,
T: Any + Send + Sync,
{
if (*self).is::<T>() {
unsafe {
Expand All @@ -1739,6 +1739,45 @@ impl Arc<dyn Any + Send + Sync> {
Err(self)
}
}

/// Downcasts the `Arc<dyn Any + Send + Sync>` 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<dyn Any + Send + Sync> = Arc::new(1_usize);
///
/// unsafe {
/// assert_eq!(*x.downcast_unchecked::<usize>(), 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<T>(self) -> Arc<T>
where
T: Any + Send + Sync,
{
unsafe {
let ptr = self.ptr.cast::<ArcInner<T>>();
mem::forget(self);
Arc::from_inner(ptr)
}
}
}

impl<T> Weak<T> {
Expand Down
7 changes: 4 additions & 3 deletions library/core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,9 +1006,10 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// // 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();
/// }
/// }
Expand Down
48 changes: 48 additions & 0 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,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")]
Expand All @@ -315,6 +356,13 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
}
}

// #[stable(feature = "slice_iter_mut_as_mut_slice", since = "FIXME")]
// impl<T> 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
Expand Down
50 changes: 34 additions & 16 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,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
///
/// ```
Expand All @@ -1105,15 +1109,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.
///
/// 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).
/// 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
///
/// Panics when trying to advance beyond the end of the slices.
///
/// # Examples
///
Expand Down Expand Up @@ -1154,7 +1161,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)
}
}
Expand Down Expand Up @@ -1219,6 +1228,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
///
/// ```
Expand All @@ -1240,15 +1253,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.
///
/// 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).
/// 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
///
/// Panics when trying to advance beyond the end of the slices.
///
/// # Examples
///
Expand Down Expand Up @@ -1288,7 +1304,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)
}
}
Expand Down
8 changes: 4 additions & 4 deletions library/std/src/io/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down Expand Up @@ -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());
}
Expand Down
19 changes: 19 additions & 0 deletions library/std/src/os/unix/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@
//! Like boxes, `OwnedFd` values conceptually own the resource they point to,
//! and free (close) it when they are dropped.
//!
//! ## `/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.
//!
//! 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
//! 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
//! 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")]
Expand Down
Loading

0 comments on commit b12708f

Please sign in to comment.