|
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