-
Notifications
You must be signed in to change notification settings - Fork 61
Open
Labels
A-validityTopic: Related to validity invariantsTopic: Related to validity invariantsC-open-questionCategory: An open question that we should revisitCategory: An open question that we should revisitS-pending-designStatus: Resolving this issue requires addressing some open design questionsStatus: Resolving this issue requires addressing some open design questions
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());
} }
Metadata
Metadata
Assignees
Labels
A-validityTopic: Related to validity invariantsTopic: Related to validity invariantsC-open-questionCategory: An open question that we should revisitCategory: An open question that we should revisitS-pending-designStatus: Resolving this issue requires addressing some open design questionsStatus: Resolving this issue requires addressing some open design questions