-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.A-raw-pointersArea: raw pointers, MaybeUninit, NonNullArea: raw pointers, MaybeUninit, NonNullA-sliceArea: `[T]`Area: `[T]`C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-opsemRelevant to the opsem teamRelevant to the opsem team
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.
bstrie
Metadata
Metadata
Assignees
Labels
A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.A-raw-pointersArea: raw pointers, MaybeUninit, NonNullArea: raw pointers, MaybeUninit, NonNullA-sliceArea: `[T]`Area: `[T]`C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-opsemRelevant to the opsem teamRelevant to the opsem team