237
237
238
238
use crate :: cmp:: Ordering ;
239
239
use crate :: fmt:: { self , Debug , Display } ;
240
+ use crate :: intrinsics:: is_nonoverlapping;
240
241
use crate :: marker:: { PhantomData , Unsize } ;
241
242
use crate :: mem;
242
243
use crate :: ops:: { CoerceUnsized , Deref , DerefMut , DispatchFromDyn } ;
@@ -415,6 +416,12 @@ impl<T> Cell<T> {
415
416
/// Swaps the values of two `Cell`s.
416
417
/// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference.
417
418
///
419
+ /// # Panics
420
+ ///
421
+ /// This function will panic if `self` and `other` are different `Cell`s that partially overlap.
422
+ /// (Using just standard library methods, it is impossible to create such partially overlapping `Cell`s.
423
+ /// However, unsafe code is allowed to e.g. create two `&Cell<[i32; 2]>` that partially overlap.)
424
+ ///
418
425
/// # Examples
419
426
///
420
427
/// ```
@@ -430,14 +437,20 @@ impl<T> Cell<T> {
430
437
#[ stable( feature = "move_cell" , since = "1.17.0" ) ]
431
438
pub fn swap ( & self , other : & Self ) {
432
439
if ptr:: eq ( self , other) {
440
+ // Swapping wouldn't change anything.
433
441
return ;
434
442
}
443
+ if !is_nonoverlapping ( self , other, 1 ) {
444
+ // See <https://github.com/rust-lang/rust/issues/80778> for why we need to stop here.
445
+ panic ! ( "`Cell::swap` on overlapping non-identical `Cell`s" ) ;
446
+ }
435
447
// SAFETY: This can be risky if called from separate threads, but `Cell`
436
448
// is `!Sync` so this won't happen. This also won't invalidate any
437
449
// pointers since `Cell` makes sure nothing else will be pointing into
438
- // either of these `Cell`s.
450
+ // either of these `Cell`s. We also excluded shenanigans like partially overlapping `Cell`s,
451
+ // so `swap` will just properly copy two full values of type `T` back and forth.
439
452
unsafe {
440
- ptr :: swap ( self . value . get ( ) , other. value . get ( ) ) ;
453
+ mem :: swap ( & mut * self . value . get ( ) , & mut * other. value . get ( ) ) ;
441
454
}
442
455
}
443
456
0 commit comments