Code change:
#[stable(feature = "move_cell", since = "1.17.0")] pub fn swap(&self, other: &Self) { if ptr::eq(self, other) { <ins> // Swapping wouldn't change anything. </ins> return; } <ins> if !is_nonoverlapping(self, other, 1) { // See <https://github.com/rust-lang/rust/issues/80778> for why we need to stop here. panic!("`Cell::swap` on overlapping non-identical `Cell`s"); } </ins> // SAFETY: This can be risky if called from separate threads, but `Cell` // is `!Sync` so this won't happen. This also won't invalidate any // pointers since `Cell` makes sure nothing else will be pointing into <del> // either of these `Cell`s. </del> <ins> // either of these `Cell`s. We also excluded shenanigans like partially overlapping `Cell`s, // so `swap` will just properly copy two full values of type `T` back and forth. </ins> unsafe { <del> ptr::swap(self.value.get(), other.value.get()); </del> <ins> mem::swap(&mut *self.value.get(), &mut *other.value.get()); </ins> } }

Related discussion:
text: Btw, also exists. does not have array/slice projection functions though and they would be wrong due to the counts, so overlapping probably truly are not a thing.
At the very least, an argument that aren't allowed to overlap is easier to defend than that aren't allowed to overlap. Plus also, doesn't have guaranteed layout in the first place, so any example using tuples is (currently) implementation-detail-tied even before hitting . You could still construct an example using only types, of course; just replace the tuple with an actual type. You could even make it . As I understand it, there's three main cases here. ping two nonoverlapping is fine. ping two partially overlapping without any bound on has a sound, if surprising, definition, where the nonoverlapping part of the arrays are swapped. ping two partially overlapping unknown is unsound in any definition, unless both has no safety invariants and the overlapping portion is . The third case is obviously the most restricting one, and is defined on . To expound on first of the two subissues: Consider a type with the extra safety invariant that the second must be double the first . could even be . It would be valid to create two from , as you'd have and . There is no possible definition of (other than a no-op) which preserves the safety invariant. And of course the impl doesn't even know about the safety invariant. I could probably create an even worse example using underaligned types and relying on a specific endianness, perhaps even accidentally breaking validity invariants (think around partially overlapping ). The only two resolutions I'm confident in are making always panic for overlapping cells (because there could be safety invariants being broken) or forbidding overlapping s to -compatible types (optionally: that would be broken by ). And I don't like the subtle implications of the latter (e.g. being unsound for unbound ).
I don't think would be immediately unsound, you would still need a way to create overlapping s.
In particular, they certainly can only overlap in restricted ways -- if they overlap such that one's sits on the other's , I can already cause UB without just by storing into that and then reading it as a . Oh I see... to only swap the non-overlapping parts we have to make an argument that these parts have the same type (safety+validity invariant).