summary refs log tree commit diff
path: root/library/core/src/intrinsics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/intrinsics.rs')
-rw-r--r--library/core/src/intrinsics.rs337
1 files changed, 186 insertions, 151 deletions
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index b5371d6b69d..073210c5b68 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1742,157 +1742,6 @@ extern "rust-intrinsic" {
     /// Allocate at compile time. Should not be called at runtime.
     #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
     pub fn const_allocate(size: usize, align: usize) -> *mut u8;
-
-    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-    /// and destination must *not* overlap.
-    ///
-    /// For regions of memory which might overlap, use [`copy`] instead.
-    ///
-    /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
-    /// with the argument order swapped.
-    ///
-    /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
-    ///
-    /// # Safety
-    ///
-    /// Behavior is undefined if any of the following conditions are violated:
-    ///
-    /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
-    ///
-    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
-    ///
-    /// * Both `src` and `dst` must be properly aligned.
-    ///
-    /// * The region of memory beginning at `src` with a size of `count *
-    ///   size_of::<T>()` bytes must *not* overlap with the region of memory
-    ///   beginning at `dst` with the same size.
-    ///
-    /// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
-    /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
-    /// in the region beginning at `*src` and the region beginning at `*dst` can
-    /// [violate memory safety][read-ownership].
-    ///
-    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-    /// `0`, the pointers must be non-NULL and properly aligned.
-    ///
-    /// [`read`]: crate::ptr::read
-    /// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
-    /// [valid]: crate::ptr#safety
-    ///
-    /// # Examples
-    ///
-    /// Manually implement [`Vec::append`]:
-    ///
-    /// ```
-    /// use std::ptr;
-    ///
-    /// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
-    /// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
-    ///     let src_len = src.len();
-    ///     let dst_len = dst.len();
-    ///
-    ///     // Ensure that `dst` has enough capacity to hold all of `src`.
-    ///     dst.reserve(src_len);
-    ///
-    ///     unsafe {
-    ///         // The call to offset is always safe because `Vec` will never
-    ///         // allocate more than `isize::MAX` bytes.
-    ///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
-    ///         let src_ptr = src.as_ptr();
-    ///
-    ///         // Truncate `src` without dropping its contents. We do this first,
-    ///         // to avoid problems in case something further down panics.
-    ///         src.set_len(0);
-    ///
-    ///         // The two regions cannot overlap because mutable references do
-    ///         // not alias, and two different vectors cannot own the same
-    ///         // memory.
-    ///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
-    ///
-    ///         // Notify `dst` that it now holds the contents of `src`.
-    ///         dst.set_len(dst_len + src_len);
-    ///     }
-    /// }
-    ///
-    /// let mut a = vec!['r'];
-    /// let mut b = vec!['u', 's', 't'];
-    ///
-    /// append(&mut a, &mut b);
-    ///
-    /// assert_eq!(a, &['r', 'u', 's', 't']);
-    /// assert!(b.is_empty());
-    /// ```
-    ///
-    /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
-    #[doc(alias = "memcpy")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
-    pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
-
-    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-    /// and destination may overlap.
-    ///
-    /// If the source and destination will *never* overlap,
-    /// [`copy_nonoverlapping`] can be used instead.
-    ///
-    /// `copy` is semantically equivalent to C's [`memmove`], but with the argument
-    /// order swapped. Copying takes place as if the bytes were copied from `src`
-    /// to a temporary array and then copied from the array to `dst`.
-    ///
-    /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
-    ///
-    /// # Safety
-    ///
-    /// Behavior is undefined if any of the following conditions are violated:
-    ///
-    /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
-    ///
-    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
-    ///
-    /// * Both `src` and `dst` must be properly aligned.
-    ///
-    /// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
-    /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
-    /// in the region beginning at `*src` and the region beginning at `*dst` can
-    /// [violate memory safety][read-ownership].
-    ///
-    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-    /// `0`, the pointers must be non-NULL and properly aligned.
-    ///
-    /// [`read`]: crate::ptr::read
-    /// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
-    /// [valid]: crate::ptr#safety
-    ///
-    /// # Examples
-    ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
-    ///
-    /// ```
-    /// use std::ptr;
-    ///
-    /// /// # Safety
-    /// ///
-    /// /// * `ptr` must be correctly aligned for its type and non-zero.
-    /// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
-    /// /// * Those elements must not be used after calling this function unless `T: Copy`.
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
-    ///
-    ///     // SAFETY: Our precondition ensures the source is aligned and valid,
-    ///     // and `Vec::with_capacity` ensures that we have usable space to write them.
-    ///     ptr::copy(ptr, dst.as_mut_ptr(), elts);
-    ///
-    ///     // SAFETY: We created it with this much capacity earlier,
-    ///     // and the previous `copy` has initialized these elements.
-    ///     dst.set_len(elts);
-    ///     dst
-    /// }
-    /// ```
-    #[doc(alias = "memmove")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
-    pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
 }
 
 // Some functions are defined here because they accidentally got made
@@ -1906,6 +1755,192 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
     !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
 }
 
+/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
+/// and destination must *not* overlap.
+///
+/// For regions of memory which might overlap, use [`copy`] instead.
+///
+/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
+/// with the argument order swapped.
+///
+/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+///
+/// * Both `src` and `dst` must be properly aligned.
+///
+/// * The region of memory beginning at `src` with a size of `count *
+///   size_of::<T>()` bytes must *not* overlap with the region of memory
+///   beginning at `dst` with the same size.
+///
+/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
+/// in the region beginning at `*src` and the region beginning at `*dst` can
+/// [violate memory safety][read-ownership].
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointers must be non-NULL and properly aligned.
+///
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Manually implement [`Vec::append`]:
+///
+/// ```
+/// use std::ptr;
+///
+/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
+/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
+///     let src_len = src.len();
+///     let dst_len = dst.len();
+///
+///     // Ensure that `dst` has enough capacity to hold all of `src`.
+///     dst.reserve(src_len);
+///
+///     unsafe {
+///         // The call to offset is always safe because `Vec` will never
+///         // allocate more than `isize::MAX` bytes.
+///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
+///         let src_ptr = src.as_ptr();
+///
+///         // Truncate `src` without dropping its contents. We do this first,
+///         // to avoid problems in case something further down panics.
+///         src.set_len(0);
+///
+///         // The two regions cannot overlap because mutable references do
+///         // not alias, and two different vectors cannot own the same
+///         // memory.
+///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
+///
+///         // Notify `dst` that it now holds the contents of `src`.
+///         dst.set_len(dst_len + src_len);
+///     }
+/// }
+///
+/// let mut a = vec!['r'];
+/// let mut b = vec!['u', 's', 't'];
+///
+/// append(&mut a, &mut b);
+///
+/// assert_eq!(a, &['r', 'u', 's', 't']);
+/// assert!(b.is_empty());
+/// ```
+///
+/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
+#[doc(alias = "memcpy")]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+#[inline]
+pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
+    extern "rust-intrinsic" {
+        #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+        fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+    }
+
+    // FIXME: Perform these checks only at run time
+    /*if cfg!(debug_assertions)
+        && !(is_aligned_and_not_null(src)
+            && is_aligned_and_not_null(dst)
+            && is_nonoverlapping(src, dst, count))
+    {
+        // Not panicking to keep codegen impact smaller.
+        abort();
+    }*/
+
+    // SAFETY: the safety contract for `copy_nonoverlapping` must be
+    // upheld by the caller.
+    unsafe { copy_nonoverlapping(src, dst, count) }
+}
+
+/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
+/// and destination may overlap.
+///
+/// If the source and destination will *never* overlap,
+/// [`copy_nonoverlapping`] can be used instead.
+///
+/// `copy` is semantically equivalent to C's [`memmove`], but with the argument
+/// order swapped. Copying takes place as if the bytes were copied from `src`
+/// to a temporary array and then copied from the array to `dst`.
+///
+/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+///
+/// * Both `src` and `dst` must be properly aligned.
+///
+/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
+/// in the region beginning at `*src` and the region beginning at `*dst` can
+/// [violate memory safety][read-ownership].
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointers must be non-NULL and properly aligned.
+///
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Efficiently create a Rust vector from an unsafe buffer:
+///
+/// ```
+/// use std::ptr;
+///
+/// /// # Safety
+/// ///
+/// /// * `ptr` must be correctly aligned for its type and non-zero.
+/// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
+/// /// * Those elements must not be used after calling this function unless `T: Copy`.
+/// # #[allow(dead_code)]
+/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
+///     let mut dst = Vec::with_capacity(elts);
+///
+///     // SAFETY: Our precondition ensures the source is aligned and valid,
+///     // and `Vec::with_capacity` ensures that we have usable space to write them.
+///     ptr::copy(ptr, dst.as_mut_ptr(), elts);
+///
+///     // SAFETY: We created it with this much capacity earlier,
+///     // and the previous `copy` has initialized these elements.
+///     dst.set_len(elts);
+///     dst
+/// }
+/// ```
+#[doc(alias = "memmove")]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+#[inline]
+pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
+    extern "rust-intrinsic" {
+        #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+        fn copy<T>(src: *const T, dst: *mut T, count: usize);
+    }
+
+    // FIXME: Perform these checks only at run time
+    /*if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)) {
+        // Not panicking to keep codegen impact smaller.
+        abort();
+    }*/
+
+    // SAFETY: the safety contract for `copy` must be upheld by the caller.
+    unsafe { copy(src, dst, count) }
+}
+
 /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
 /// `val`.
 ///