diff options
| author | bors <bors@rust-lang.org> | 2023-08-31 06:20:39 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-08-31 06:20:39 +0000 |
| commit | 2518c0ffeb112b5ecf409c5ea7825b46bb3db8ec (patch) | |
| tree | c5f0f668af52a644dad21229e18c952893832fb1 /library | |
| parent | d9c11c65ee93b6dfd0c71f17812c68d316fce183 (diff) | |
| parent | f57b41519dc3bd863650114c344e8e7db7a1cc2d (diff) | |
Auto merge of #3044 - rust-lang:rustup-2023-08-31, r=RalfJung
Automatic sync from rustc
Diffstat (limited to 'library')
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 51 | ||||
| -rw-r--r-- | library/core/src/cell.rs | 17 | ||||
| -rw-r--r-- | library/core/src/intrinsics.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/hermit/mod.rs | 5 |
4 files changed, 72 insertions, 3 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e45ddc7896b..ae7bac0c85f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1218,6 +1218,15 @@ impl<T, A: Allocator> Vec<T, A> { /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize mutable references to the slice, + /// or mutable references to specific elements you are planning on accessing through this pointer, + /// as well as writing to those elements, may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. + /// + /// /// # Examples /// /// ``` @@ -1231,7 +1240,23 @@ impl<T, A: Allocator> Vec<T, A> { /// } /// ``` /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// unsafe { + /// let mut v = vec![0, 1, 2]; + /// let ptr1 = v.as_ptr(); + /// let _ = ptr1.read(); + /// let ptr2 = v.as_mut_ptr().offset(2); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1` + /// // because it mutated a different element: + /// let _ = ptr1.read(); + /// } + /// ``` + /// /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[inline] pub fn as_ptr(&self) -> *const T { @@ -1248,6 +1273,15 @@ impl<T, A: Allocator> Vec<T, A> { /// Modifying the vector may cause its buffer to be reallocated, /// which would also make any pointers to it invalid. /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize references to the slice, + /// or references to specific elements you are planning on accessing through this pointer, + /// may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. + /// + /// /// # Examples /// /// ``` @@ -1265,6 +1299,23 @@ impl<T, A: Allocator> Vec<T, A> { /// } /// assert_eq!(&*x, &[0, 1, 2, 3]); /// ``` + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// unsafe { + /// let mut v = vec![0]; + /// let ptr1 = v.as_mut_ptr(); + /// ptr1.write(1); + /// let ptr2 = v.as_mut_ptr(); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 4bbe61ca3e7..28950a43d2d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -237,6 +237,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; +use crate::intrinsics::is_nonoverlapping; use crate::marker::{PhantomData, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn}; @@ -415,6 +416,12 @@ impl<T> Cell<T> { /// Swaps the values of two `Cell`s. /// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference. /// + /// # Panics + /// + /// This function will panic if `self` and `other` are different `Cell`s that partially overlap. + /// (Using just standard library methods, it is impossible to create such partially overlapping `Cell`s. + /// However, unsafe code is allowed to e.g. create two `&Cell<[i32; 2]>` that partially overlap.) + /// /// # Examples /// /// ``` @@ -430,14 +437,20 @@ impl<T> Cell<T> { #[stable(feature = "move_cell", since = "1.17.0")] pub fn swap(&self, other: &Self) { if ptr::eq(self, other) { + // Swapping wouldn't change anything. return; } + if !is_nonoverlapping(self, other, 1) { + // See <https://github.com/rust-lang/rust/issues/80778> for why we need to stop here. + panic!("`Cell::swap` on overlapping non-identical `Cell`s"); + } // SAFETY: This can be risky if called from separate threads, but `Cell` // is `!Sync` so this won't happen. This also won't invalidate any // pointers since `Cell` makes sure nothing else will be pointing into - // either of these `Cell`s. + // either of these `Cell`s. We also excluded shenanigans like partially overlapping `Cell`s, + // so `swap` will just properly copy two full values of type `T` back and forth. unsafe { - ptr::swap(self.value.get(), other.value.get()); + mem::swap(&mut *self.value.get(), &mut *other.value.get()); } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 605870b8a7b..eafbaba9ef3 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2567,7 +2567,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - let size = mem::size_of::<T>() .checked_mul(count) .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); - let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; + let diff = src_usize.abs_diff(dst_usize); // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. diff >= size diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index fb22d3e22cd..744cb0c911b 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -129,6 +129,11 @@ pub unsafe extern "C" fn runtime_entry( abi::exit(result); } +#[inline] +pub(crate) fn is_interrupted(errno: i32) -> bool { + errno == abi::errno::EINTR +} + pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno { abi::errno::EACCES => ErrorKind::PermissionDenied, |
