@@ -740,26 +740,19 @@ pub const fn swap<T>(x: &mut T, y: &mut T) {
740
740
#[ rustc_const_unstable( feature = "const_swap" , issue = "83163" ) ]
741
741
#[ inline]
742
742
pub ( crate ) const fn swap_simple < T > ( x : & mut T , y : & mut T ) {
743
- // We arrange for this to typically be called with small types,
744
- // so this reads-and-writes approach is actually better than using
745
- // copy_nonoverlapping as it easily puts things in LLVM registers
746
- // directly and doesn't end up inlining allocas.
747
- // And LLVM actually optimizes it to 3×memcpy if called with
748
- // a type larger than it's willing to keep in a register.
749
- // Having typed reads and writes in MIR here is also good as
750
- // it lets MIRI and CTFE understand them better, including things
751
- // like enforcing type validity for them.
743
+ // Make sure the same operations are done on the two sides.
752
744
// Importantly, read+copy_nonoverlapping+write introduces confusing
753
745
// asymmetry to the behaviour where one value went through read+write
754
746
// whereas the other was copied over by the intrinsic (see #94371).
755
747
756
748
// SAFETY: exclusive references are always valid to read/write,
757
749
// including being aligned, and nothing here panics so it's drop-safe.
758
750
unsafe {
759
- let a = ptr:: read ( x) ;
760
- let b = ptr:: read ( y) ;
761
- ptr:: write ( x, b) ;
762
- ptr:: write ( y, a) ;
751
+ let mut z = MaybeUninit :: < T > :: uninit ( ) ;
752
+ let z = z. as_mut_ptr ( ) ;
753
+ ptr:: copy_nonoverlapping ( x, z, 1 ) ;
754
+ ptr:: copy_nonoverlapping ( y, x, 1 ) ;
755
+ ptr:: copy_nonoverlapping ( z, y, 1 ) ;
763
756
}
764
757
}
765
758
0 commit comments