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/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 2b3736019ba40..a248cd458df81 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1254,8 +1254,6 @@ impl Rc { } impl Rc { - #[inline] - #[stable(feature = "rc_downcast", since = "1.29.0")] /// Attempt to downcast the `Rc` to a concrete type. /// /// # Examples @@ -1274,6 +1272,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 { @@ -1285,6 +1285,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 55d51e0a3c4cf..2670b15982ad9 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1705,8 +1705,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 @@ -1725,9 +1723,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 { @@ -1739,6 +1739,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 { 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(); /// } /// } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 772a9698d84cc..35d00b9dda663 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -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 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 diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 94812e3fe3b2c..cad1fab7b8f84 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -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) } } 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()); } diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 7556d3ad0b230..3ab5606f8897d 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -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")] diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 24b0888b11256..a6b75493e6e60 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")] diff --git a/library/std/src/process.rs b/library/std/src/process.rs index da8eee9030b90..ab1a1e6c76fa4 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 { 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`.