I wonder why in rust a *mut T
can refer to a slice of T
. Wouldn't that have to be a *mut [T]
?
I ask because the following works
#[repr(C)]
pub struct Array<T> {
len: usize,
ptr: *mut T,
}
impl<T: Copy> Array<T> {
fn new(val: T, len: usize) -> Self {
let data = vec![val; len].into_boxed_slice();
Self {
len: len as usize,
ptr: Box::into_raw(data).cast(),
}
}
}
Why can I do Box::into_raw(data).cast()
casting from a *mut [T]
to a *mut T
without losing provenance over the elements following the first one? If I do something similar with a reference I get UB.
fn main() {
let mut a = [0; 4];
let p0 = &mut a[0];
unsafe{
let ptr0 = p0 as *mut i32;
let ptr2 = ptr0.add(2);
*ptr2 = 12;
}
dbg!(a);
}
error: Undefined Behavior: attempting a write access using <1616> at alloc918[0x8], but that tag does not exist in the borrow stack for this location
--> src/main.rs:7:9
|
7 | *ptr2 = 12;
| ^^^^^^^^^^
| |
| attempting a write access using <1616> at alloc918[0x8], but that tag does not exist in the borrow stack for this location
| this error occurs as part of an access at alloc918[0x8..0xc]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <1616> was created by a SharedReadWrite retag at offsets [0x0..0x4]
--> src/main.rs:5:20
|
5 | let ptr0 = p0 as *mut i32;
| ^^
= note: BACKTRACE (of the first span):
= note: inside `main` at src/main.rs:7:9: 7:19
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error