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: In , it was uncovered that is making some rather strong assumptions: two s with different address but the same type must not overlap. Not only is this a scarily non-local safety invariant, it is also fundamentally incomaptible with some APIs that ought to be correct, as demonstrated by this snippet (thanks to and for help with working out the example): to see the issue: will duplicate parts of the memory range when there is overlap, which leads to double-drop (other parts of the memory range are just lost, leading to memory leaks, but that is not the main issue here). This is not itself a soundness issue as it requires unsafe code to trigger UB. But this likely reflects an unintended consequence of . This got stabilized in as part of That commit references and an RFC, but is not mentioned in either of them. was in Accept that is unsound and document "non-overlap" as part of the safety invariant. This seems very fragile. Make not misbehave on overlap, either by panicking or by only swapping the non-overlapping parts. Cc
was in , which was authored by a "Charlie Fan". This is probably
Cc
This makes the method sound, but it seems like there could be other seems-like-they-should-be-ok cell projections that break under this behavior.
I don't think so. This makes the function behave "strangely", but since no data is duplicated nor discarded, I think it is sound.
I share this hunch, although the code, out of nowhere, may look very contrived. Consider: So it seems like -king (at least for non- types) is the only option that would allow us too keep the structural property of s, which, imho, is a very intuitive programmer mindset (and thus, a mistake that many would do should they not know about this caveat), and so a quite important thing to preserve .
That is an example of the "strange" behavior not being the right thing for this code, but it is not an unsoundness of per se. Your unsafe code is simply making wrong assumptions about the functional behavior of . Current favors the first operand in case of overlap (according to documentation); unsafe code that incorrectly assumes it would favor the second operand would be equally wrong. I don't see a bug in either way. IMO it seems rather strange to only panic for non- types.