#[stable(feature = "drop_in_place", since = "1.8.0")]
#[rustc_deprecated(
reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
- since = "1.18.0"
+ since = "1.52.0"
)]
-pub use crate::ptr::drop_in_place;
+#[inline]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // SAFETY: see `ptr::drop_in_place`
+ unsafe { crate::ptr::drop_in_place(to_drop) }
+}
extern "rust-intrinsic" {
// N.B., these intrinsics take raw pointers because they mutate aliased
///
/// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
/// `ManuallyDrop` instead.
+ #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
pub fn forget<T: ?Sized>(_: T);
/// Reinterprets the bits of a value of one type as another type.
/// destination value, then forgets the original. It's equivalent to C's
/// `memcpy` under the hood, just like `transmute_copy`.
///
+ /// Because `transmute` is a by-value operation, alignment of the *transmuted values
+ /// themselves* is not a concern. As with any other function, the compiler already ensures
+ /// both `T` and `U` are properly aligned. However, when transmuting values that *point
+ /// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper
+ /// alignment of the pointed-to values.
+ ///
/// `transmute` is **incredibly** unsafe. There are a vast number of ways to
/// cause [undefined behavior][ub] with this function. `transmute` should be
/// the absolute last resort.
/// assert_eq!(b"Rust", &[82, 117, 115, 116]);
/// ```
///
- /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
+ /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`.
+ ///
+ /// To transmute the inner type of the contents of a container, you must make sure to not
+ /// violate any of the container's invariants. For `Vec`, this means that both the size
+ /// *and alignment* of the inner types have to match. Other containers might rely on the
+ /// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't
+ /// be possible at all without violating the container invariants.
///
/// ```
/// let store = [0, 1, 2, 3];
///
/// let v_clone = v_orig.clone();
///
- /// // The no-copy, unsafe way, still using transmute, but not relying on the data layout.
- /// // Like the first approach, this reuses the `Vec` internals.
- /// // Therefore, the new inner type must have the
- /// // exact same size, *and the same alignment*, as the old type.
- /// // The same caveats exist for this method as transmute, for
- /// // the original inner type (`&i32`) to the converted inner type
- /// // (`Option<&i32>`), so read the nomicon pages linked above and also
- /// // consult the [`from_raw_parts`] documentation.
+ /// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the
+ /// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but
+ /// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`),
+ /// // this has all the same caveats. Besides the information provided above, also consult the
+ /// // [`from_raw_parts`] documentation.
/// let v_from_raw = unsafe {
// FIXME Update this when vec_into_raw_parts is stabilized
/// // Ensure the original vector is not dropped.
/// bounds or arithmetic overflow occurs then any further use of the
/// returned value will result in undefined behavior.
///
- /// The stabilized version of this intrinsic is
- /// [`std::pointer::offset`](../../std/primitive.pointer.html#method.offset).
+ /// The stabilized version of this intrinsic is [`pointer::offset`].
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
/// object, and it wraps with two's complement arithmetic. The resulting
/// value is not necessarily valid to be used to actually access memory.
///
- /// The stabilized version of this intrinsic is
- /// [`std::pointer::wrapping_offset`](../../std/primitive.pointer.html#method.wrapping_offset).
+ /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
/// Safe wrappers for this intrinsic are available on the integer
/// primitives via the `checked_div` method. For example,
/// [`u32::checked_div`]
- #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
+ #[rustc_const_stable(feature = "const_int_unchecked_arith", since = "1.52.0")]
pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked division, resulting in
/// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
/// Safe wrappers for this intrinsic are available on the integer
/// primitives via the `checked_rem` method. For example,
/// [`u32::checked_rem`]
- #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
+ #[rustc_const_stable(feature = "const_int_unchecked_arith", since = "1.52.0")]
pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
/// Performs an unchecked left shift, resulting in undefined behavior when
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
- /// Returns the value of the discriminant for the variant in 'v',
- /// cast to a `u64`; if `T` has no discriminant, returns `0`.
+ /// Returns the value of the discriminant for the variant in 'v';
+ /// if `T` has no discriminant, returns `0`.
///
/// The stabilized version of this intrinsic is [`core::mem::discriminant`](crate::mem::discriminant).
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
!ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
}
-/// Checks whether the regions of memory starting at `src` and `dst` of size
-/// `count * size_of::<T>()` do *not* overlap.
-pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
- let src_usize = src as usize;
- let dst_usize = dst as usize;
- let size = mem::size_of::<T>().checked_mul(count).unwrap();
- let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_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
-}
-
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
/// and destination must *not* overlap.
///