|
| 1 | +### Example |
| 2 | + |
| 3 | +```rust |
| 4 | +impl [T] { |
| 5 | + pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { |
| 6 | + let copy: &mut [T] = unsafe { mem::transmute_copy(&self) }; |
| 7 | + let left = &mut self[0..mid]; |
| 8 | + let right = &mut copy[mid..]; |
| 9 | + (left, right) |
| 10 | + } |
| 11 | +} |
| 12 | +``` |
| 13 | + |
| 14 | +### Explanation |
| 15 | + |
| 16 | +it cheats the compiler by |
| 17 | +"duplicating" `self` using the unsafe function |
| 18 | +[`transmute_copy`][transmute_copy]. This means that both `self` and |
| 19 | +`copy` are `&mut [T]` slices pointing at the same memory, at the same |
| 20 | +time. In ordinary, safe Rust, this is impossible, but using |
| 21 | +`transmute_copy`, we can make it happen. |
| 22 | + |
| 23 | +The rest of the function looks almost the same as our original attempt |
| 24 | +at a safe implementation (also in the [previous post][pp]). The only |
| 25 | +difference now is that, in defining `right`, it uses `copy[mid..]` |
| 26 | +instead of `self[mid..]`. The compiler accepts this because it assumes |
| 27 | +that `copy` and `self`, since they are both simultaneously valid, must |
| 28 | +be disjoint (remember that, in unsafe code, the borrow checker still |
| 29 | +enforces its rules on safe typess, it's just that we can use tricks |
| 30 | +like raw pointers or transmutes to sidestep them). |
| 31 | + |
| 32 | +So this raises a question -- is this legal unsafe code to write, given |
| 33 | +that it is only accepted because the borrowck thinks (incorrectly) |
| 34 | +that `self` and `copy` are disjoint? |
| 35 | + |
| 36 | +### Source |
| 37 | + |
| 38 | +Rust sources. |
0 commit comments