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