Open
Description
(Taken from #69 (comment).)
How do we feel about this code -- UB or not?
fn main() { unsafe {
let mut x = Some(&0);
match x {
Some(ref mut b) => {
let u = b as *mut &i32 as *mut usize;
// Just writing into a *mut u8
*u = 0;
}
None => panic!(),
}
assert!(x.is_some());
} }
This "magically" changes the discriminant. OTOH, it is very similar to
fn main() { unsafe {
let mut x = Some(&0);
(&mut x as *mut _ as *mut usize) = 0;
assert!(x.is_some());
} }
which is definitely allowed (it makes assumptions about layout, but we do guarantee layout of Option<&T>
.
Other examples:
fn main() { unsafe {
let mut x = true;
let xptr = &mut x as *mut bool as *mut u8;
*xptr = 2;
} }
fn main() { unsafe {
let mut x = Some(true);
match x {
Some(ref mut b) => {
let u = b as *mut bool as *mut u8;
// Just writing into a *mut u8
*u = 2;
}
None => panic!(),
}
assert!(x.is_some());
} }
#![feature(rustc_attrs)]
#[rustc_layout_scalar_valid_range_start(1)]
#[repr(transparent)]
pub(crate) struct NonZero(u32);
fn main() { unsafe {
let mut x = Some(NonZero(1));
match x {
Some(NonZero(ref mut c)) => {
// Just writing 0 into an &mut u32
*c = 0;
}
None => panic!(),
}
assert!(x.is_some());
} }