Auto merge of #98292 - Dylan-DPC:rollup-hueb8tm, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #93080 (Implement `core::slice::IterMut::as_mut_slice` and `impl<T> AsMut<[T]> for IterMut<'_, T>`) - #94855 (Panic when advance_slices()'ing too far and update docs.) - #96609 (Add `{Arc, Rc}::downcast_unchecked`) - #96719 (Fix the generator example for `pin!()`) - #97149 (Windows: `CommandExt::async_pipes`) - #97150 (`Stdio::makes_pipe`) - #97837 (Document Rust's stance on `/proc/self/mem`) - #98159 (Include ForeignItem when visiting types for WF check) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
b12708f7f4
@ -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 } => {
|
||||
|
@ -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
|
||||
@ -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 {
|
||||
@ -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> {
|
||||
|
@ -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
|
||||
@ -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 {
|
||||
@ -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> {
|
||||
|
@ -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();
|
||||
/// }
|
||||
/// }
|
||||
|
@ -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")]
|
||||
@ -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
|
||||
|
@ -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
|
||||
///
|
||||
/// ```
|
||||
@ -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
|
||||
///
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
///
|
||||
/// ```
|
||||
@ -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
|
||||
///
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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")]
|
||||
|
@ -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<S: AsRef<OsStr>>(&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")]
|
||||
|
@ -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<imp::Stdio> for Stdio {
|
||||
|
18
src/test/ui/wf/issue-95665.rs
Normal file
18
src/test/ui/wf/issue-95665.rs
Normal file
@ -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<T: Trait> {
|
||||
member: T,
|
||||
}
|
||||
|
||||
// uncomment and bug goes away
|
||||
// impl Trait for u8 {}
|
||||
|
||||
extern "C" {
|
||||
static VAR: Struct<u8>;
|
||||
//~^ 14:17: 14:27: the trait bound `u8: Trait` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn main() {}
|
15
src/test/ui/wf/issue-95665.stderr
Normal file
15
src/test/ui/wf/issue-95665.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0277]: the trait bound `u8: Trait` is not satisfied
|
||||
--> $DIR/issue-95665.rs:14:17
|
||||
|
|
||||
LL | static VAR: Struct<u8>;
|
||||
| ^^^^^^^^^^ 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<T: Trait> {
|
||||
| ^^^^^ required by this bound in `Struct`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
x
Reference in New Issue
Block a user