Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constify copy related functions #83091

Merged
merged 4 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1902,18 +1902,6 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
!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
}

/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
/// `val`.
///
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
#![feature(const_slice_from_raw_parts)]
#![feature(const_slice_ptr_len)]
#![feature(const_size_of_val)]
#![feature(const_swap)]
#![feature(const_align_of_val)]
#![feature(const_type_id)]
#![feature(const_type_name)]
Expand Down
9 changes: 6 additions & 3 deletions library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,8 @@ pub unsafe fn uninitialized<T>() -> T {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
pub const fn swap<T>(x: &mut T, y: &mut T) {
// SAFETY: the raw pointers have been created from safe mutable references satisfying all the
// constraints on `ptr::swap_nonoverlapping_one`
unsafe {
Expand Down Expand Up @@ -812,7 +813,8 @@ pub fn take<T: Default>(dest: &mut T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "if you don't need the old value, you can just assign the new value directly"]
pub fn replace<T>(dest: &mut T, src: T) -> T {
#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
pub const fn replace<T>(dest: &mut T, src: T) -> T {
// SAFETY: We read from `dest` but directly write `src` into it afterwards,
// such that the old value is not duplicated. Nothing is dropped and
// nothing here can panic.
Expand Down Expand Up @@ -931,7 +933,8 @@ pub fn drop<T>(_x: T) {}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
// If U has a higher alignment requirement, src may not be suitably aligned.
if align_of::<U>() > align_of::<T>() {
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.
Expand Down
6 changes: 4 additions & 2 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,9 +819,10 @@ impl<T: ?Sized> *const T {
/// See [`ptr::copy`] for safety concerns and examples.
///
/// [`ptr::copy`]: crate::ptr::copy()
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[inline]
pub unsafe fn copy_to(self, dest: *mut T, count: usize)
pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
where
T: Sized,
{
Expand All @@ -837,9 +838,10 @@ impl<T: ?Sized> *const T {
/// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
///
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[inline]
pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
where
T: Sized,
{
Expand Down
26 changes: 11 additions & 15 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
use crate::cmp::Ordering;
use crate::fmt;
use crate::hash;
use crate::intrinsics::{self, abort, is_aligned_and_not_null, is_nonoverlapping};
use crate::intrinsics::{self, abort, is_aligned_and_not_null};
use crate::mem::{self, MaybeUninit};

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -394,7 +394,8 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
// Give ourselves some scratch space to work with.
// We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
let mut tmp = MaybeUninit::<T>::uninit();
Expand Down Expand Up @@ -451,16 +452,8 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
/// ```
#[inline]
#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
if cfg!(debug_assertions)
&& !(is_aligned_and_not_null(x)
&& is_aligned_and_not_null(y)
&& is_nonoverlapping(x, y, count))
{
// Not panicking to keep codegen impact smaller.
abort();
}

#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
let len = mem::size_of::<T>() * count;
Expand All @@ -470,7 +463,8 @@ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
}

#[inline]
pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
pub(crate) const unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
if mem::size_of::<T>() < 32 {
Expand All @@ -488,7 +482,8 @@ pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
}

#[inline]
unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
// The approach here is to utilize simd to swap x & y efficiently. Testing reveals
// that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
// Haswell E processors. LLVM is more able to optimize if we give a struct a
Expand Down Expand Up @@ -589,7 +584,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
// SAFETY: the caller must guarantee that `dst` is valid to be
// cast to a mutable reference (valid for writes, aligned, initialized),
// and cannot overlap `src` since `dst` must point to a distinct
Expand Down
12 changes: 8 additions & 4 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,9 +926,10 @@ impl<T: ?Sized> *mut T {
/// See [`ptr::copy`] for safety concerns and examples.
///
/// [`ptr::copy`]: crate::ptr::copy()
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[inline]
pub unsafe fn copy_to(self, dest: *mut T, count: usize)
pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
where
T: Sized,
{
Expand All @@ -944,9 +945,10 @@ impl<T: ?Sized> *mut T {
/// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
///
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[inline]
pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
where
T: Sized,
{
Expand All @@ -962,9 +964,10 @@ impl<T: ?Sized> *mut T {
/// See [`ptr::copy`] for safety concerns and examples.
///
/// [`ptr::copy`]: crate::ptr::copy()
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[inline]
pub unsafe fn copy_from(self, src: *const T, count: usize)
pub const unsafe fn copy_from(self, src: *const T, count: usize)
where
T: Sized,
{
Expand All @@ -980,9 +983,10 @@ impl<T: ?Sized> *mut T {
/// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
///
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[inline]
pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
pub const unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
where
T: Sized,
{
Expand Down