Open
Description
So let's say you know about aliasing models and have learned that to avoid all aliasing rules of Rust you need to use raw pointers throughout, no references. So for example you write:
use std::ptr::addr_of_mut;
pub fn test(ptr: *mut [u8]) -> *mut [u8] {
let layout_size = 24;
unsafe { addr_of_mut!((*(ptr))[..layout_size]) }
}
Looks good, doesn't it?
Well sadly the MIR for this code looks as follows:
fn test(_1: *mut [u8]) -> *mut [u8] {
debug ptr => _1; // in scope 0 at [src/lib.rs:3:13: 3:16](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
let mut _0: *mut [u8]; // return place in scope 0 at [src/lib.rs:3:32: 3:41](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
let _2: usize; // in scope 0 at [src/lib.rs:4:9: 4:20](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
let mut _3: &mut [u8]; // in scope 0 at [src/lib.rs:5:27: 5:50](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
let mut _4: &mut [u8]; // in scope 0 at [src/lib.rs:5:27: 5:35](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
let mut _5: std::ops::RangeTo<usize>; // in scope 0 at [src/lib.rs:5:36: 5:49](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
scope 1 {
debug layout_size => _2; // in scope 1 at [src/lib.rs:4:9: 4:20](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
scope 2 {
}
}
bb0: {
_2 = const 24_usize; // scope 0 at [src/lib.rs:4:23: 4:25](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
_4 = &mut (*_1); // scope 2 at [src/lib.rs:5:27: 5:35](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
Deinit(_5); // scope 2 at [src/lib.rs:5:36: 5:49](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
(_5.0: usize) = const 24_usize; // scope 2 at [src/lib.rs:5:36: 5:49](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
_3 = <[u8] as IndexMut<RangeTo<usize>>>::index_mut(move _4, move _5) -> bb1; // scope 2 at [src/lib.rs:5:27: 5:50](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
// mir::Constant
// + span: [src/lib.rs:5:27: 5:50](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
// + literal: Const { ty: for<'r> fn(&'r mut [u8], RangeTo<usize>) -> &'r mut <[u8] as Index<RangeTo<usize>>>::Output {<[u8] as IndexMut<RangeTo<usize>>>::index_mut}, val: Value(<ZST>) }
}
bb1: {
_0 = &raw mut (*_3); // scope 2 at /rustc/263edd43c5255084292329423c61a9d69715ebfa/library/core/src/ptr/mod.rs:2005:5: 2005:20
return; // scope 0 at [src/lib.rs:6:2: 6:2](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#)
}
}
Note the _4 = &mut (*_1)
: Rust "helpfully" created a reference for us to subslice into!
This is terrible, because it introduces UB.
This code should either be rejected, or use raw pointers throughout.
Related to #73987.