395395#![ allow( clippy:: not_unsafe_ptr_arg_deref) ]
396396
397397use crate :: cmp:: Ordering ;
398+ use crate :: intrinsics:: const_eval_select;
398399use crate :: marker:: FnPtr ;
399400use crate :: mem:: { self , MaybeUninit , SizedTypeProperties } ;
400401use crate :: { fmt, hash, intrinsics, ub_checks} ;
@@ -1074,25 +1075,6 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
10741075#[ rustc_const_unstable( feature = "const_swap_nonoverlapping" , issue = "133668" ) ]
10751076#[ rustc_diagnostic_item = "ptr_swap_nonoverlapping" ]
10761077pub const unsafe fn swap_nonoverlapping < T > ( x : * mut T , y : * mut T , count : usize ) {
1077- #[ allow( unused) ]
1078- macro_rules! attempt_swap_as_chunks {
1079- ( $ChunkTy: ty) => {
1080- if mem:: align_of:: <T >( ) >= mem:: align_of:: <$ChunkTy>( )
1081- && mem:: size_of:: <T >( ) % mem:: size_of:: <$ChunkTy>( ) == 0
1082- {
1083- let x: * mut $ChunkTy = x. cast( ) ;
1084- let y: * mut $ChunkTy = y. cast( ) ;
1085- let count = count * ( mem:: size_of:: <T >( ) / mem:: size_of:: <$ChunkTy>( ) ) ;
1086- // SAFETY: these are the same bytes that the caller promised were
1087- // ok, just typed as `MaybeUninit<ChunkTy>`s instead of as `T`s.
1088- // The `if` condition above ensures that we're not violating
1089- // alignment requirements, and that the division is exact so
1090- // that we don't lose any bytes off the end.
1091- return unsafe { swap_nonoverlapping_simple_untyped( x, y, count) } ;
1092- }
1093- } ;
1094- }
1095-
10961078 ub_checks:: assert_unsafe_precondition!(
10971079 check_language_ub,
10981080 "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \
@@ -1111,19 +1093,48 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
11111093 }
11121094 ) ;
11131095
1114- // Split up the slice into small power-of-two-sized chunks that LLVM is able
1115- // to vectorize (unless it's a special type with more-than-pointer alignment,
1116- // because we don't want to pessimize things like slices of SIMD vectors.)
1117- if mem:: align_of :: < T > ( ) <= mem:: size_of :: < usize > ( )
1118- && ( !mem:: size_of :: < T > ( ) . is_power_of_two ( )
1119- || mem:: size_of :: < T > ( ) > mem:: size_of :: < usize > ( ) * 2 )
1120- {
1121- attempt_swap_as_chunks ! ( usize ) ;
1122- attempt_swap_as_chunks ! ( u8 ) ;
1123- }
1096+ const_eval_select ! (
1097+ @capture[ T ] { x: * mut T , y: * mut T , count: usize } :
1098+ if const {
1099+ // At compile-time we want to always copy this in chunks of `T`, to ensure that if there
1100+ // are pointers inside `T` we will copy them in one go rather than trying to copy a part
1101+ // of a pointer (which would not work).
1102+ // SAFETY: Same preconditions as this function
1103+ unsafe { swap_nonoverlapping_simple_untyped( x, y, count) }
1104+ } else {
1105+ macro_rules! attempt_swap_as_chunks {
1106+ ( $ChunkTy : ty) => {
1107+ if mem:: align_of:: <T >( ) >= mem:: align_of:: <$ChunkTy >( )
1108+ && mem:: size_of:: <T >( ) % mem:: size_of:: <$ChunkTy >( ) == 0
1109+ {
1110+ let x: * mut $ChunkTy = x. cast( ) ;
1111+ let y: * mut $ChunkTy = y. cast( ) ;
1112+ let count = count * ( mem:: size_of:: <T >( ) / mem:: size_of:: <$ChunkTy >( ) ) ;
1113+ // SAFETY: these are the same bytes that the caller promised were
1114+ // ok, just typed as `MaybeUninit<ChunkTy>`s instead of as `T`s.
1115+ // The `if` condition above ensures that we're not violating
1116+ // alignment requirements, and that the division is exact so
1117+ // that we don't lose any bytes off the end.
1118+ return unsafe { swap_nonoverlapping_simple_untyped( x, y, count) } ;
1119+ }
1120+ } ;
1121+ }
1122+
1123+ // Split up the slice into small power-of-two-sized chunks that LLVM is able
1124+ // to vectorize (unless it's a special type with more-than-pointer alignment,
1125+ // because we don't want to pessimize things like slices of SIMD vectors.)
1126+ if mem:: align_of:: <T >( ) <= mem:: size_of:: <usize >( )
1127+ && ( !mem:: size_of:: <T >( ) . is_power_of_two( )
1128+ || mem:: size_of:: <T >( ) > mem:: size_of:: <usize >( ) * 2 )
1129+ {
1130+ attempt_swap_as_chunks!( usize ) ;
1131+ attempt_swap_as_chunks!( u8 ) ;
1132+ }
11241133
1125- // SAFETY: Same preconditions as this function
1126- unsafe { swap_nonoverlapping_simple_untyped ( x, y, count) }
1134+ // SAFETY: Same preconditions as this function
1135+ unsafe { swap_nonoverlapping_simple_untyped( x, y, count) }
1136+ }
1137+ )
11271138}
11281139
11291140/// Same behavior and safety conditions as [`swap_nonoverlapping`]
0 commit comments