Skip to content

Commit 64e2248

Browse files
committed
Constify mem::swap and ptr::swap[_nonoverlapping]
1 parent 62cf244 commit 64e2248

File tree

4 files changed

+12
-27
lines changed

4 files changed

+12
-27
lines changed

library/core/src/intrinsics.rs

-12
Original file line numberDiff line numberDiff line change
@@ -1902,18 +1902,6 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
19021902
!ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
19031903
}
19041904

1905-
/// Checks whether the regions of memory starting at `src` and `dst` of size
1906-
/// `count * size_of::<T>()` do *not* overlap.
1907-
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
1908-
let src_usize = src as usize;
1909-
let dst_usize = dst as usize;
1910-
let size = mem::size_of::<T>().checked_mul(count).unwrap();
1911-
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
1912-
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
1913-
// they do not overlap.
1914-
diff >= size
1915-
}
1916-
19171905
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
19181906
/// `val`.
19191907
///

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
#![feature(const_slice_from_raw_parts)]
9999
#![feature(const_slice_ptr_len)]
100100
#![feature(const_size_of_val)]
101+
#![feature(const_swap)]
101102
#![feature(const_align_of_val)]
102103
#![feature(const_type_id)]
103104
#![feature(const_type_name)]

library/core/src/mem/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,8 @@ pub unsafe fn uninitialized<T>() -> T {
682682
/// ```
683683
#[inline]
684684
#[stable(feature = "rust1", since = "1.0.0")]
685-
pub fn swap<T>(x: &mut T, y: &mut T) {
685+
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
686+
pub const fn swap<T>(x: &mut T, y: &mut T) {
686687
// SAFETY: the raw pointers have been created from safe mutable references satisfying all the
687688
// constraints on `ptr::swap_nonoverlapping_one`
688689
unsafe {

library/core/src/ptr/mod.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
use crate::cmp::Ordering;
6868
use crate::fmt;
6969
use crate::hash;
70-
use crate::intrinsics::{self, abort, is_aligned_and_not_null, is_nonoverlapping};
70+
use crate::intrinsics::{self, abort, is_aligned_and_not_null};
7171
use crate::mem::{self, MaybeUninit};
7272

7373
#[stable(feature = "rust1", since = "1.0.0")]
@@ -394,7 +394,8 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
394394
/// ```
395395
#[inline]
396396
#[stable(feature = "rust1", since = "1.0.0")]
397-
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
397+
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
398+
pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
398399
// Give ourselves some scratch space to work with.
399400
// We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
400401
let mut tmp = MaybeUninit::<T>::uninit();
@@ -451,16 +452,8 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
451452
/// ```
452453
#[inline]
453454
#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
454-
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
455-
if cfg!(debug_assertions)
456-
&& !(is_aligned_and_not_null(x)
457-
&& is_aligned_and_not_null(y)
458-
&& is_nonoverlapping(x, y, count))
459-
{
460-
// Not panicking to keep codegen impact smaller.
461-
abort();
462-
}
463-
455+
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
456+
pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
464457
let x = x as *mut u8;
465458
let y = y as *mut u8;
466459
let len = mem::size_of::<T>() * count;
@@ -470,7 +463,8 @@ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
470463
}
471464

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

490484
#[inline]
491-
unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
485+
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
486+
const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
492487
// The approach here is to utilize simd to swap x & y efficiently. Testing reveals
493488
// that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
494489
// Haswell E processors. LLVM is more able to optimize if we give a struct a

0 commit comments

Comments
 (0)