|
62 | 62 | #![allow(missing_docs)]
|
63 | 63 |
|
64 | 64 | use crate::marker::{DiscriminantKind, Tuple};
|
65 |
| -use crate::mem::SizedTypeProperties; |
66 |
| -use crate::{ptr, ub_checks}; |
| 65 | +use crate::ptr; |
67 | 66 |
|
68 | 67 | pub mod fallback;
|
69 | 68 | pub mod mir;
|
@@ -3317,7 +3316,7 @@ pub const unsafe fn typed_swap_nonoverlapping<T>(x: *mut T, y: *mut T) {
|
3317 | 3316 | /// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(ub_checks)` means that
|
3318 | 3317 | /// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the
|
3319 | 3318 | /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is
|
3320 |
| -/// primarily used by [`ub_checks::assert_unsafe_precondition`]. |
| 3319 | +/// primarily used by [`crate::ub_checks::assert_unsafe_precondition`]. |
3321 | 3320 | #[rustc_intrinsic_const_stable_indirect] // just for UB checks
|
3322 | 3321 | #[inline(always)]
|
3323 | 3322 | #[rustc_intrinsic]
|
@@ -3595,306 +3594,38 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
|
3595 | 3594 | #[rustc_intrinsic]
|
3596 | 3595 | pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(ptr: *const P) -> M;
|
3597 | 3596 |
|
3598 |
| -// Some functions are defined here because they accidentally got made |
3599 |
| -// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>. |
3600 |
| -// (`transmute` also falls into this category, but it cannot be wrapped due to the |
3601 |
| -// check that `T` and `U` have the same size.) |
3602 |
| - |
3603 |
| -/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source |
3604 |
| -/// and destination must *not* overlap. |
3605 |
| -/// |
3606 |
| -/// For regions of memory which might overlap, use [`copy`] instead. |
3607 |
| -/// |
3608 |
| -/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but |
3609 |
| -/// with the source and destination arguments swapped, |
3610 |
| -/// and `count` counting the number of `T`s instead of bytes. |
3611 |
| -/// |
3612 |
| -/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the |
3613 |
| -/// requirements of `T`. The initialization state is preserved exactly. |
3614 |
| -/// |
3615 |
| -/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy |
3616 |
| -/// |
3617 |
| -/// # Safety |
3618 |
| -/// |
3619 |
| -/// Behavior is undefined if any of the following conditions are violated: |
3620 |
| -/// |
3621 |
| -/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes. |
3622 |
| -/// |
3623 |
| -/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes. |
3624 |
| -/// |
3625 |
| -/// * Both `src` and `dst` must be properly aligned. |
3626 |
| -/// |
3627 |
| -/// * The region of memory beginning at `src` with a size of `count * |
3628 |
| -/// size_of::<T>()` bytes must *not* overlap with the region of memory |
3629 |
| -/// beginning at `dst` with the same size. |
3630 |
| -/// |
3631 |
| -/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of |
3632 |
| -/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values |
3633 |
| -/// in the region beginning at `*src` and the region beginning at `*dst` can |
3634 |
| -/// [violate memory safety][read-ownership]. |
3635 |
| -/// |
3636 |
| -/// Note that even if the effectively copied size (`count * size_of::<T>()`) is |
3637 |
| -/// `0`, the pointers must be properly aligned. |
3638 |
| -/// |
3639 |
| -/// [`read`]: crate::ptr::read |
3640 |
| -/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value |
3641 |
| -/// [valid]: crate::ptr#safety |
3642 |
| -/// |
3643 |
| -/// # Examples |
3644 |
| -/// |
3645 |
| -/// Manually implement [`Vec::append`]: |
3646 |
| -/// |
3647 |
| -/// ``` |
3648 |
| -/// use std::ptr; |
3649 |
| -/// |
3650 |
| -/// /// Moves all the elements of `src` into `dst`, leaving `src` empty. |
3651 |
| -/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) { |
3652 |
| -/// let src_len = src.len(); |
3653 |
| -/// let dst_len = dst.len(); |
3654 |
| -/// |
3655 |
| -/// // Ensure that `dst` has enough capacity to hold all of `src`. |
3656 |
| -/// dst.reserve(src_len); |
3657 |
| -/// |
3658 |
| -/// unsafe { |
3659 |
| -/// // The call to add is always safe because `Vec` will never |
3660 |
| -/// // allocate more than `isize::MAX` bytes. |
3661 |
| -/// let dst_ptr = dst.as_mut_ptr().add(dst_len); |
3662 |
| -/// let src_ptr = src.as_ptr(); |
3663 |
| -/// |
3664 |
| -/// // Truncate `src` without dropping its contents. We do this first, |
3665 |
| -/// // to avoid problems in case something further down panics. |
3666 |
| -/// src.set_len(0); |
3667 |
| -/// |
3668 |
| -/// // The two regions cannot overlap because mutable references do |
3669 |
| -/// // not alias, and two different vectors cannot own the same |
3670 |
| -/// // memory. |
3671 |
| -/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); |
3672 |
| -/// |
3673 |
| -/// // Notify `dst` that it now holds the contents of `src`. |
3674 |
| -/// dst.set_len(dst_len + src_len); |
3675 |
| -/// } |
3676 |
| -/// } |
3677 |
| -/// |
3678 |
| -/// let mut a = vec!['r']; |
3679 |
| -/// let mut b = vec!['u', 's', 't']; |
3680 |
| -/// |
3681 |
| -/// append(&mut a, &mut b); |
3682 |
| -/// |
3683 |
| -/// assert_eq!(a, &['r', 'u', 's', 't']); |
3684 |
| -/// assert!(b.is_empty()); |
3685 |
| -/// ``` |
3686 |
| -/// |
3687 |
| -/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append |
3688 |
| -#[doc(alias = "memcpy")] |
| 3597 | +/// This is an accidentally-stable alias to [`ptr::copy_nonoverlapping`]; use that instead. |
| 3598 | +// Note (intentionally not in the doc comment): `ptr::copy_nonoverlapping` adds some extra |
| 3599 | +// debug assertions; if you are writing compiler tests or code inside the standard library |
| 3600 | +// that wants to avoid those debug assertions, directly call this intrinsic instead. |
3689 | 3601 | #[stable(feature = "rust1", since = "1.0.0")]
|
3690 | 3602 | #[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"]
|
3691 | 3603 | #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
|
3692 |
| -#[inline(always)] |
3693 |
| -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces |
3694 |
| -#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] |
3695 |
| -pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { |
3696 |
| - #[rustc_intrinsic_const_stable_indirect] |
3697 |
| - #[rustc_nounwind] |
3698 |
| - #[rustc_intrinsic] |
3699 |
| - const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); |
3700 |
| - |
3701 |
| - ub_checks::assert_unsafe_precondition!( |
3702 |
| - check_language_ub, |
3703 |
| - "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ |
3704 |
| - and the specified memory ranges do not overlap", |
3705 |
| - ( |
3706 |
| - src: *const () = src as *const (), |
3707 |
| - dst: *mut () = dst as *mut (), |
3708 |
| - size: usize = size_of::<T>(), |
3709 |
| - align: usize = align_of::<T>(), |
3710 |
| - count: usize = count, |
3711 |
| - ) => { |
3712 |
| - let zero_size = count == 0 || size == 0; |
3713 |
| - ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) |
3714 |
| - && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) |
3715 |
| - && ub_checks::maybe_is_nonoverlapping(src, dst, size, count) |
3716 |
| - } |
3717 |
| - ); |
3718 |
| - |
3719 |
| - // SAFETY: the safety contract for `copy_nonoverlapping` must be |
3720 |
| - // upheld by the caller. |
3721 |
| - unsafe { copy_nonoverlapping(src, dst, count) } |
3722 |
| -} |
| 3604 | +#[rustc_nounwind] |
| 3605 | +#[rustc_intrinsic] |
| 3606 | +pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); |
3723 | 3607 |
|
3724 |
| -/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source |
3725 |
| -/// and destination may overlap. |
3726 |
| -/// |
3727 |
| -/// If the source and destination will *never* overlap, |
3728 |
| -/// [`copy_nonoverlapping`] can be used instead. |
3729 |
| -/// |
3730 |
| -/// `copy` is semantically equivalent to C's [`memmove`], but |
3731 |
| -/// with the source and destination arguments swapped, |
3732 |
| -/// and `count` counting the number of `T`s instead of bytes. |
3733 |
| -/// Copying takes place as if the bytes were copied from `src` |
3734 |
| -/// to a temporary array and then copied from the array to `dst`. |
3735 |
| -/// |
3736 |
| -/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the |
3737 |
| -/// requirements of `T`. The initialization state is preserved exactly. |
3738 |
| -/// |
3739 |
| -/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove |
3740 |
| -/// |
3741 |
| -/// # Safety |
3742 |
| -/// |
3743 |
| -/// Behavior is undefined if any of the following conditions are violated: |
3744 |
| -/// |
3745 |
| -/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes. |
3746 |
| -/// |
3747 |
| -/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes, and must remain valid even |
3748 |
| -/// when `src` is read for `count * size_of::<T>()` bytes. (This means if the memory ranges |
3749 |
| -/// overlap, the `dst` pointer must not be invalidated by `src` reads.) |
3750 |
| -/// |
3751 |
| -/// * Both `src` and `dst` must be properly aligned. |
3752 |
| -/// |
3753 |
| -/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of |
3754 |
| -/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values |
3755 |
| -/// in the region beginning at `*src` and the region beginning at `*dst` can |
3756 |
| -/// [violate memory safety][read-ownership]. |
3757 |
| -/// |
3758 |
| -/// Note that even if the effectively copied size (`count * size_of::<T>()`) is |
3759 |
| -/// `0`, the pointers must be properly aligned. |
3760 |
| -/// |
3761 |
| -/// [`read`]: crate::ptr::read |
3762 |
| -/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value |
3763 |
| -/// [valid]: crate::ptr#safety |
3764 |
| -/// |
3765 |
| -/// # Examples |
3766 |
| -/// |
3767 |
| -/// Efficiently create a Rust vector from an unsafe buffer: |
3768 |
| -/// |
3769 |
| -/// ``` |
3770 |
| -/// use std::ptr; |
3771 |
| -/// |
3772 |
| -/// /// # Safety |
3773 |
| -/// /// |
3774 |
| -/// /// * `ptr` must be correctly aligned for its type and non-zero. |
3775 |
| -/// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`. |
3776 |
| -/// /// * Those elements must not be used after calling this function unless `T: Copy`. |
3777 |
| -/// # #[allow(dead_code)] |
3778 |
| -/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> { |
3779 |
| -/// let mut dst = Vec::with_capacity(elts); |
3780 |
| -/// |
3781 |
| -/// // SAFETY: Our precondition ensures the source is aligned and valid, |
3782 |
| -/// // and `Vec::with_capacity` ensures that we have usable space to write them. |
3783 |
| -/// unsafe { ptr::copy(ptr, dst.as_mut_ptr(), elts); } |
3784 |
| -/// |
3785 |
| -/// // SAFETY: We created it with this much capacity earlier, |
3786 |
| -/// // and the previous `copy` has initialized these elements. |
3787 |
| -/// unsafe { dst.set_len(elts); } |
3788 |
| -/// dst |
3789 |
| -/// } |
3790 |
| -/// ``` |
3791 |
| -#[doc(alias = "memmove")] |
| 3608 | +/// This is an accidentally-stable alias to [`ptr::copy`]; use that instead. |
| 3609 | +// Note (intentionally not in the doc comment): `ptr::copy` adds some extra |
| 3610 | +// debug assertions; if you are writing compiler tests or code inside the standard library |
| 3611 | +// that wants to avoid those debug assertions, directly call this intrinsic instead. |
3792 | 3612 | #[stable(feature = "rust1", since = "1.0.0")]
|
3793 | 3613 | #[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"]
|
3794 | 3614 | #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
|
3795 |
| -#[inline(always)] |
3796 |
| -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces |
3797 |
| -#[rustc_diagnostic_item = "ptr_copy"] |
3798 |
| -pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { |
3799 |
| - #[rustc_intrinsic_const_stable_indirect] |
3800 |
| - #[rustc_nounwind] |
3801 |
| - #[rustc_intrinsic] |
3802 |
| - const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize); |
3803 |
| - |
3804 |
| - // SAFETY: the safety contract for `copy` must be upheld by the caller. |
3805 |
| - unsafe { |
3806 |
| - ub_checks::assert_unsafe_precondition!( |
3807 |
| - check_language_ub, |
3808 |
| - "ptr::copy requires that both pointer arguments are aligned and non-null", |
3809 |
| - ( |
3810 |
| - src: *const () = src as *const (), |
3811 |
| - dst: *mut () = dst as *mut (), |
3812 |
| - align: usize = align_of::<T>(), |
3813 |
| - zero_size: bool = T::IS_ZST || count == 0, |
3814 |
| - ) => |
3815 |
| - ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) |
3816 |
| - && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) |
3817 |
| - ); |
3818 |
| - copy(src, dst, count) |
3819 |
| - } |
3820 |
| -} |
| 3615 | +#[rustc_nounwind] |
| 3616 | +#[rustc_intrinsic] |
| 3617 | +pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize); |
3821 | 3618 |
|
3822 |
| -/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to |
3823 |
| -/// `val`. |
3824 |
| -/// |
3825 |
| -/// `write_bytes` is similar to C's [`memset`], but sets `count * |
3826 |
| -/// size_of::<T>()` bytes to `val`. |
3827 |
| -/// |
3828 |
| -/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset |
3829 |
| -/// |
3830 |
| -/// # Safety |
3831 |
| -/// |
3832 |
| -/// Behavior is undefined if any of the following conditions are violated: |
3833 |
| -/// |
3834 |
| -/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes. |
3835 |
| -/// |
3836 |
| -/// * `dst` must be properly aligned. |
3837 |
| -/// |
3838 |
| -/// Note that even if the effectively copied size (`count * size_of::<T>()`) is |
3839 |
| -/// `0`, the pointer must be properly aligned. |
3840 |
| -/// |
3841 |
| -/// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB) |
3842 |
| -/// later if the written bytes are not a valid representation of some `T`. For instance, the |
3843 |
| -/// following is an **incorrect** use of this function: |
3844 |
| -/// |
3845 |
| -/// ```rust,no_run |
3846 |
| -/// unsafe { |
3847 |
| -/// let mut value: u8 = 0; |
3848 |
| -/// let ptr: *mut bool = &mut value as *mut u8 as *mut bool; |
3849 |
| -/// let _bool = ptr.read(); // This is fine, `ptr` points to a valid `bool`. |
3850 |
| -/// ptr.write_bytes(42u8, 1); // This function itself does not cause UB... |
3851 |
| -/// let _bool = ptr.read(); // ...but it makes this operation UB! ⚠️ |
3852 |
| -/// } |
3853 |
| -/// ``` |
3854 |
| -/// |
3855 |
| -/// [valid]: crate::ptr#safety |
3856 |
| -/// |
3857 |
| -/// # Examples |
3858 |
| -/// |
3859 |
| -/// Basic usage: |
3860 |
| -/// |
3861 |
| -/// ``` |
3862 |
| -/// use std::ptr; |
3863 |
| -/// |
3864 |
| -/// let mut vec = vec![0u32; 4]; |
3865 |
| -/// unsafe { |
3866 |
| -/// let vec_ptr = vec.as_mut_ptr(); |
3867 |
| -/// ptr::write_bytes(vec_ptr, 0xfe, 2); |
3868 |
| -/// } |
3869 |
| -/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]); |
3870 |
| -/// ``` |
3871 |
| -#[doc(alias = "memset")] |
| 3619 | +/// This is an accidentally-stable alias to [`ptr::write_bytes`]; use that instead. |
| 3620 | +// Note (intentionally not in the doc comment): `ptr::write_bytes` adds some extra |
| 3621 | +// debug assertions; if you are writing compiler tests or code inside the standard library |
| 3622 | +// that wants to avoid those debug assertions, directly call this intrinsic instead. |
3872 | 3623 | #[stable(feature = "rust1", since = "1.0.0")]
|
3873 | 3624 | #[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"]
|
3874 |
| -#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] |
3875 |
| -#[inline(always)] |
3876 |
| -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces |
3877 |
| -#[rustc_diagnostic_item = "ptr_write_bytes"] |
3878 |
| -pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { |
3879 |
| - #[rustc_intrinsic_const_stable_indirect] |
3880 |
| - #[rustc_nounwind] |
3881 |
| - #[rustc_intrinsic] |
3882 |
| - const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize); |
3883 |
| - |
3884 |
| - // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. |
3885 |
| - unsafe { |
3886 |
| - ub_checks::assert_unsafe_precondition!( |
3887 |
| - check_language_ub, |
3888 |
| - "ptr::write_bytes requires that the destination pointer is aligned and non-null", |
3889 |
| - ( |
3890 |
| - addr: *const () = dst as *const (), |
3891 |
| - align: usize = align_of::<T>(), |
3892 |
| - zero_size: bool = T::IS_ZST || count == 0, |
3893 |
| - ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, zero_size) |
3894 |
| - ); |
3895 |
| - write_bytes(dst, val, count) |
3896 |
| - } |
3897 |
| -} |
| 3625 | +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] |
| 3626 | +#[rustc_nounwind] |
| 3627 | +#[rustc_intrinsic] |
| 3628 | +pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize); |
3898 | 3629 |
|
3899 | 3630 | /// Returns the minimum (IEEE 754-2008 minNum) of two `f16` values.
|
3900 | 3631 | ///
|
|
0 commit comments