237237
238238use crate :: cmp:: Ordering ;
239239use crate :: fmt:: { self , Debug , Display } ;
240+ use crate :: intrinsics:: is_nonoverlapping;
240241use crate :: marker:: { PhantomData , Unsize } ;
241242use crate :: mem;
242243use crate :: ops:: { CoerceUnsized , Deref , DerefMut , DispatchFromDyn } ;
@@ -415,6 +416,12 @@ impl<T> Cell<T> {
415416 /// Swaps the values of two `Cell`s.
416417 /// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference.
417418 ///
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+ ///
418425 /// # Examples
419426 ///
420427 /// ```
@@ -430,14 +437,20 @@ impl<T> Cell<T> {
430437 #[ stable( feature = "move_cell" , since = "1.17.0" ) ]
431438 pub fn swap ( & self , other : & Self ) {
432439 if ptr:: eq ( self , other) {
440+ // Swapping wouldn't change anything.
433441 return ;
434442 }
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+ }
435447 // SAFETY: This can be risky if called from separate threads, but `Cell`
436448 // is `!Sync` so this won't happen. This also won't invalidate any
437449 // 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.
439452 unsafe {
440- ptr :: swap ( self . value . get ( ) , other. value . get ( ) ) ;
453+ mem :: swap ( & mut * self . value . get ( ) , & mut * other. value . get ( ) ) ;
441454 }
442455 }
443456
0 commit comments