@@ -1064,10 +1064,43 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
1064
1064
/// assert_eq!(x, [7, 8, 3, 4]);
1065
1065
/// assert_eq!(y, [1, 2, 9]);
1066
1066
/// ```
1067
+ ///
1068
+ /// # Const evaluation limitations
1069
+ ///
1070
+ /// If this function is invoked during const-evaluation, the current implementation has a small (and
1071
+ /// rarely relevant) limitation: if `count` is at least 2 and the data pointed to by `x` or `y`
1072
+ /// contains a pointer that crosses the boundary of two `T`-sized chunks of memory, the function
1073
+ /// may fail.
1074
+ /// This is illustrated by the following example:
1075
+ ///
1076
+ /// ```
1077
+ /// use std::mem::size_of;
1078
+ /// use std::ptr;
1079
+ ///
1080
+ /// const { unsafe {
1081
+ /// const PTR_SIZE: usize = size_of::<*const i32>();
1082
+ /// let mut data1 = [0u8; PTR_SIZE];
1083
+ /// let mut data2 = [0u8; PTR_SIZE];
1084
+ /// // Store a pointer in `data1`.
1085
+ /// data1.as_mut_ptr().cast::<*const i32>().write_unaligned(&42);
1086
+ /// // Swap the contents of `data1` and `data2` by swapping `PTR_SIZE` many `u8`-sized chunks.
1087
+ /// // This call will fail, because the pointer in `data1` crosses the boundary
1088
+ /// // between several of the 1-byte chunks that are being swapped here.
1089
+ /// //ptr::swap_nonoverlapping(data1.as_mut_ptr(), data2.as_mut_ptr(), PTR_SIZE);
1090
+ /// // Swap the contents of `data1` and `data2` by swapping a single chunk of size
1091
+ /// // `[u8; PTR_SIZE]`. That works, as there is no pointer crossing the boundary between
1092
+ /// // two chunks.
1093
+ /// ptr::swap_nonoverlapping(&mut data1, &mut data2, 1);
1094
+ /// // Read the pointer from `data2` and dereference it.
1095
+ /// let ptr = data2.as_ptr().cast::<*const i32>().read_unaligned();
1096
+ /// assert!(*ptr == 42);
1097
+ /// } }
1098
+ /// ```
1067
1099
#[ inline]
1068
1100
#[ stable( feature = "swap_nonoverlapping" , since = "1.27.0" ) ]
1069
- #[ rustc_const_unstable ( feature = "const_swap_nonoverlapping" , issue = "133668 " ) ]
1101
+ #[ rustc_const_stable ( feature = "const_swap_nonoverlapping" , since = "CURRENT_RUSTC_VERSION " ) ]
1070
1102
#[ rustc_diagnostic_item = "ptr_swap_nonoverlapping" ]
1103
+ #[ rustc_allow_const_fn_unstable( const_eval_select) ] // both implementations behave the same
1071
1104
pub const unsafe fn swap_nonoverlapping < T > ( x : * mut T , y : * mut T , count : usize ) {
1072
1105
ub_checks:: assert_unsafe_precondition!(
1073
1106
check_library_ub,
0 commit comments