Skip to content

Commit b12708f

Browse files
committed
Auto merge of rust-lang#98292 - Dylan-DPC:rollup-hueb8tm, r=Dylan-DPC
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
2 parents 1d60108 + 7bde23b commit b12708f

File tree

12 files changed

+282
-29
lines changed

12 files changed

+282
-29
lines changed

compiler/rustc_typeck/src/hir_wf_check.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::collect::ItemCtxt;
22
use rustc_hir as hir;
33
use rustc_hir::intravisit::{self, Visitor};
4-
use rustc_hir::HirId;
4+
use rustc_hir::{ForeignItem, ForeignItemKind, HirId};
55
use rustc_infer::infer::TyCtxtInferExt;
66
use rustc_infer::traits::TraitEngine;
77
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
@@ -141,6 +141,9 @@ fn diagnostic_hir_wf_check<'tcx>(
141141
ref item => bug!("Unexpected item {:?}", item),
142142
},
143143
hir::Node::Field(field) => Some(field.ty),
144+
hir::Node::ForeignItem(ForeignItem {
145+
kind: ForeignItemKind::Static(ty, _), ..
146+
}) => Some(*ty),
144147
ref node => bug!("Unexpected node {:?}", node),
145148
},
146149
WellFormedLoc::Param { function: _, param_idx } => {

library/alloc/src/rc.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -1254,8 +1254,6 @@ impl<T: Clone> Rc<T> {
12541254
}
12551255

12561256
impl Rc<dyn Any> {
1257-
#[inline]
1258-
#[stable(feature = "rc_downcast", since = "1.29.0")]
12591257
/// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
12601258
///
12611259
/// # Examples
@@ -1274,6 +1272,8 @@ impl Rc<dyn Any> {
12741272
/// print_if_string(Rc::new(my_string));
12751273
/// print_if_string(Rc::new(0i8));
12761274
/// ```
1275+
#[inline]
1276+
#[stable(feature = "rc_downcast", since = "1.29.0")]
12771277
pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>> {
12781278
if (*self).is::<T>() {
12791279
unsafe {
@@ -1285,6 +1285,42 @@ impl Rc<dyn Any> {
12851285
Err(self)
12861286
}
12871287
}
1288+
1289+
/// Downcasts the `Rc<dyn Any>` to a concrete type.
1290+
///
1291+
/// For a safe alternative see [`downcast`].
1292+
///
1293+
/// # Examples
1294+
///
1295+
/// ```
1296+
/// #![feature(downcast_unchecked)]
1297+
///
1298+
/// use std::any::Any;
1299+
/// use std::rc::Rc;
1300+
///
1301+
/// let x: Rc<dyn Any> = Rc::new(1_usize);
1302+
///
1303+
/// unsafe {
1304+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1305+
/// }
1306+
/// ```
1307+
///
1308+
/// # Safety
1309+
///
1310+
/// The contained value must be of type `T`. Calling this method
1311+
/// with the incorrect type is *undefined behavior*.
1312+
///
1313+
///
1314+
/// [`downcast`]: Self::downcast
1315+
#[inline]
1316+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1317+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T> {
1318+
unsafe {
1319+
let ptr = self.ptr.cast::<RcBox<T>>();
1320+
mem::forget(self);
1321+
Rc::from_inner(ptr)
1322+
}
1323+
}
12881324
}
12891325

12901326
impl<T: ?Sized> Rc<T> {

library/alloc/src/sync.rs

+42-3
Original file line numberDiff line numberDiff line change
@@ -1705,8 +1705,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
17051705
}
17061706

17071707
impl Arc<dyn Any + Send + Sync> {
1708-
#[inline]
1709-
#[stable(feature = "rc_downcast", since = "1.29.0")]
17101708
/// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
17111709
///
17121710
/// # Examples
@@ -1725,9 +1723,11 @@ impl Arc<dyn Any + Send + Sync> {
17251723
/// print_if_string(Arc::new(my_string));
17261724
/// print_if_string(Arc::new(0i8));
17271725
/// ```
1726+
#[inline]
1727+
#[stable(feature = "rc_downcast", since = "1.29.0")]
17281728
pub fn downcast<T>(self) -> Result<Arc<T>, Self>
17291729
where
1730-
T: Any + Send + Sync + 'static,
1730+
T: Any + Send + Sync,
17311731
{
17321732
if (*self).is::<T>() {
17331733
unsafe {
@@ -1739,6 +1739,45 @@ impl Arc<dyn Any + Send + Sync> {
17391739
Err(self)
17401740
}
17411741
}
1742+
1743+
/// Downcasts the `Arc<dyn Any + Send + Sync>` to a concrete type.
1744+
///
1745+
/// For a safe alternative see [`downcast`].
1746+
///
1747+
/// # Examples
1748+
///
1749+
/// ```
1750+
/// #![feature(downcast_unchecked)]
1751+
///
1752+
/// use std::any::Any;
1753+
/// use std::sync::Arc;
1754+
///
1755+
/// let x: Arc<dyn Any + Send + Sync> = Arc::new(1_usize);
1756+
///
1757+
/// unsafe {
1758+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1759+
/// }
1760+
/// ```
1761+
///
1762+
/// # Safety
1763+
///
1764+
/// The contained value must be of type `T`. Calling this method
1765+
/// with the incorrect type is *undefined behavior*.
1766+
///
1767+
///
1768+
/// [`downcast`]: Self::downcast
1769+
#[inline]
1770+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1771+
pub unsafe fn downcast_unchecked<T>(self) -> Arc<T>
1772+
where
1773+
T: Any + Send + Sync,
1774+
{
1775+
unsafe {
1776+
let ptr = self.ptr.cast::<ArcInner<T>>();
1777+
mem::forget(self);
1778+
Arc::from_inner(ptr)
1779+
}
1780+
}
17421781
}
17431782

17441783
impl<T> Weak<T> {

library/core/src/pin.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1006,9 +1006,10 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
10061006
/// // Allow generator to be self-referential (not `Unpin`)
10071007
/// // vvvvvv so that locals can cross yield points.
10081008
/// static || {
1009-
/// let foo = String::from("foo"); // --+
1010-
/// yield 0; // | <- crosses yield point!
1011-
/// println!("{}", &foo); // <----------+
1009+
/// let foo = String::from("foo");
1010+
/// let foo_ref = &foo; // ------+
1011+
/// yield 0; // | <- crosses yield point!
1012+
/// println!("{foo_ref}"); // <--+
10121013
/// yield foo.len();
10131014
/// }
10141015
/// }

library/core/src/slice/iter.rs

+48
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,47 @@ impl<'a, T> IterMut<'a, T> {
306306
pub fn as_slice(&self) -> &[T] {
307307
self.make_slice()
308308
}
309+
310+
/// Views the underlying data as a mutable subslice of the original data.
311+
///
312+
/// To avoid creating `&mut [T]` references that alias, the returned slice
313+
/// borrows its lifetime from the iterator the method is applied on.
314+
///
315+
/// # Examples
316+
///
317+
/// Basic usage:
318+
///
319+
/// ```
320+
/// #![feature(slice_iter_mut_as_mut_slice)]
321+
///
322+
/// let mut slice: &mut [usize] = &mut [1, 2, 3];
323+
///
324+
/// // First, we get the iterator:
325+
/// let mut iter = slice.iter_mut();
326+
/// // Then, we get a mutable slice from it:
327+
/// let mut_slice = iter.as_mut_slice();
328+
/// // So if we check what the `as_mut_slice` method returned, we have "[1, 2, 3]":
329+
/// assert_eq!(mut_slice, &mut [1, 2, 3]);
330+
///
331+
/// // We can use it to mutate the slice:
332+
/// mut_slice[0] = 4;
333+
/// mut_slice[2] = 5;
334+
///
335+
/// // Next, we can move to the second element of the slice, checking that
336+
/// // it yields the value we just wrote:
337+
/// assert_eq!(iter.next(), Some(&mut 4));
338+
/// // Now `as_mut_slice` returns "[2, 5]":
339+
/// assert_eq!(iter.as_mut_slice(), &mut [2, 5]);
340+
/// ```
341+
#[must_use]
342+
// FIXME: Uncomment the `AsMut<[T]>` impl when this gets stabilized.
343+
#[unstable(feature = "slice_iter_mut_as_mut_slice", issue = "93079")]
344+
pub fn as_mut_slice(&mut self) -> &mut [T] {
345+
// SAFETY: the iterator was created from a mutable slice with pointer
346+
// `self.ptr` and length `len!(self)`. This guarantees that all the prerequisites
347+
// for `from_raw_parts_mut` are fulfilled.
348+
unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) }
349+
}
309350
}
310351

311352
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
@@ -315,6 +356,13 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
315356
}
316357
}
317358

359+
// #[stable(feature = "slice_iter_mut_as_mut_slice", since = "FIXME")]
360+
// impl<T> AsMut<[T]> for IterMut<'_, T> {
361+
// fn as_mut(&mut self) -> &mut [T] {
362+
// self.as_mut_slice()
363+
// }
364+
// }
365+
318366
iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}}
319367

320368
/// An internal abstraction over the splitting iterators, so that

library/std/src/io/mod.rs

+34-16
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,10 @@ impl<'a> IoSliceMut<'a> {
10841084
/// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
10851085
/// multiple buffers.
10861086
///
1087+
/// # Panics
1088+
///
1089+
/// Panics when trying to advance beyond the end of the slice.
1090+
///
10871091
/// # Examples
10881092
///
10891093
/// ```
@@ -1105,15 +1109,18 @@ impl<'a> IoSliceMut<'a> {
11051109
self.0.advance(n)
11061110
}
11071111

1108-
/// Advance the internal cursor of the slices.
1112+
/// Advance a slice of slices.
11091113
///
1110-
/// # Notes
1114+
/// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over.
1115+
/// If the cursor ends up in the middle of an `IoSliceMut`, it is modified
1116+
/// to start at that cursor.
11111117
///
1112-
/// Elements in the slice may be modified if the cursor is not advanced to
1113-
/// the end of the slice. For example if we have a slice of buffers with 2
1114-
/// `IoSliceMut`s, both of length 8, and we advance the cursor by 10 bytes
1115-
/// the first `IoSliceMut` will be untouched however the second will be
1116-
/// modified to remove the first 2 bytes (10 - 8).
1118+
/// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes,
1119+
/// the result will only include the second `IoSliceMut`, advanced by 2 bytes.
1120+
///
1121+
/// # Panics
1122+
///
1123+
/// Panics when trying to advance beyond the end of the slices.
11171124
///
11181125
/// # Examples
11191126
///
@@ -1154,7 +1161,9 @@ impl<'a> IoSliceMut<'a> {
11541161
}
11551162

11561163
*bufs = &mut replace(bufs, &mut [])[remove..];
1157-
if !bufs.is_empty() {
1164+
if bufs.is_empty() {
1165+
assert!(n == accumulated_len, "advancing io slices beyond their length");
1166+
} else {
11581167
bufs[0].advance(n - accumulated_len)
11591168
}
11601169
}
@@ -1219,6 +1228,10 @@ impl<'a> IoSlice<'a> {
12191228
/// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
12201229
/// buffers.
12211230
///
1231+
/// # Panics
1232+
///
1233+
/// Panics when trying to advance beyond the end of the slice.
1234+
///
12221235
/// # Examples
12231236
///
12241237
/// ```
@@ -1240,15 +1253,18 @@ impl<'a> IoSlice<'a> {
12401253
self.0.advance(n)
12411254
}
12421255

1243-
/// Advance the internal cursor of the slices.
1256+
/// Advance a slice of slices.
12441257
///
1245-
/// # Notes
1258+
/// Shrinks the slice to remove any `IoSlice`s that are fully advanced over.
1259+
/// If the cursor ends up in the middle of an `IoSlice`, it is modified
1260+
/// to start at that cursor.
12461261
///
1247-
/// Elements in the slice may be modified if the cursor is not advanced to
1248-
/// the end of the slice. For example if we have a slice of buffers with 2
1249-
/// `IoSlice`s, both of length 8, and we advance the cursor by 10 bytes the
1250-
/// first `IoSlice` will be untouched however the second will be modified to
1251-
/// remove the first 2 bytes (10 - 8).
1262+
/// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes,
1263+
/// the result will only include the second `IoSlice`, advanced by 2 bytes.
1264+
///
1265+
/// # Panics
1266+
///
1267+
/// Panics when trying to advance beyond the end of the slices.
12521268
///
12531269
/// # Examples
12541270
///
@@ -1288,7 +1304,9 @@ impl<'a> IoSlice<'a> {
12881304
}
12891305

12901306
*bufs = &mut replace(bufs, &mut [])[remove..];
1291-
if !bufs.is_empty() {
1307+
if bufs.is_empty() {
1308+
assert!(n == accumulated_len, "advancing io slices beyond their length");
1309+
} else {
12921310
bufs[0].advance(n - accumulated_len)
12931311
}
12941312
}

library/std/src/io/tests.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -423,18 +423,18 @@ fn io_slice_mut_advance_slices() {
423423
}
424424

425425
#[test]
426+
#[should_panic]
426427
fn io_slice_mut_advance_slices_empty_slice() {
427428
let mut empty_bufs = &mut [][..];
428-
// Shouldn't panic.
429429
IoSliceMut::advance_slices(&mut empty_bufs, 1);
430430
}
431431

432432
#[test]
433+
#[should_panic]
433434
fn io_slice_mut_advance_slices_beyond_total_length() {
434435
let mut buf1 = [1; 8];
435436
let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
436437

437-
// Going beyond the total length should be ok.
438438
IoSliceMut::advance_slices(&mut bufs, 9);
439439
assert!(bufs.is_empty());
440440
}
@@ -463,18 +463,18 @@ fn io_slice_advance_slices() {
463463
}
464464

465465
#[test]
466+
#[should_panic]
466467
fn io_slice_advance_slices_empty_slice() {
467468
let mut empty_bufs = &mut [][..];
468-
// Shouldn't panic.
469469
IoSlice::advance_slices(&mut empty_bufs, 1);
470470
}
471471

472472
#[test]
473+
#[should_panic]
473474
fn io_slice_advance_slices_beyond_total_length() {
474475
let buf1 = [1; 8];
475476
let mut bufs = &mut [IoSlice::new(&buf1)][..];
476477

477-
// Going beyond the total length should be ok.
478478
IoSlice::advance_slices(&mut bufs, 9);
479479
assert!(bufs.is_empty());
480480
}

library/std/src/os/unix/io/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@
5454
//! Like boxes, `OwnedFd` values conceptually own the resource they point to,
5555
//! and free (close) it when they are dropped.
5656
//!
57+
//! ## `/proc/self/mem` and similar OS features
58+
//!
59+
//! Some platforms have special files, such as `/proc/self/mem`, which
60+
//! provide read and write access to the process's memory. Such reads
61+
//! and writes happen outside the control of the Rust compiler, so they do not
62+
//! uphold Rust's memory safety guarantees.
63+
//!
64+
//! This does not mean that all APIs that might allow `/proc/self/mem`
65+
//! to be opened and read from or written must be `unsafe`. Rust's safety guarantees
66+
//! only cover what the program itself can do, and not what entities outside
67+
//! the program can do to it. `/proc/self/mem` is considered to be such an
68+
//! external entity, along with debugging interfaces, and people with physical access to
69+
//! the hardware. This is true even in cases where the program is controlling
70+
//! the external entity.
71+
//!
72+
//! If you desire to comprehensively prevent programs from reaching out and
73+
//! causing external entities to reach back in and violate memory safety, it's
74+
//! necessary to use *sandboxing*, which is outside the scope of `std`.
75+
//!
5776
//! [`BorrowedFd<'a>`]: crate::os::unix::io::BorrowedFd
5877
5978
#![stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)