Translating "bad but compliant with the C standard" C code into Rust shows that we have the same pointer semantics as the C language, while rustc differs greatly and has less undefined behavior in the example below. This is the proper Rust version, re-add commented out lines for the gccrs compatible one.
// #![feature(intrinsics)]
// #[lang = "sized"]
// pub trait Sized {}
static Y: i32 = 2;
static X: i32 = 1;
extern "C" {
fn printf(fmt: *const i8, ...);
}
// extern "rust-intrinsic" {
// fn transmute<T, U>(_: T) -> U;
// fn size_of<T>() -> usize;
// }
use std::mem::transmute;
fn ptr_to_usize(x: *const i32) -> usize {
unsafe { transmute::<*const i32, usize>(x) }
}
fn usize_to_ptr(x: usize) -> *const i32 {
unsafe { transmute::<usize, *const i32>(x) }
}
fn bugzilla_report() {
let p: *const i32;
p = usize_to_ptr(ptr_to_usize(&X as *const i32) + 4);
unsafe {
printf(
"&X=%p &Y=%p p=%p\n\0" as *const str as *const i8,
&X as *const i32,
&Y as *const i32,
p,
)
}
let b1 = p == &Y as *const i32;
unsafe {
printf(
"(p==&Y) = %d\n\0" as *const str as *const i8,
if b1 { 1 } else { 0 },
)
}
}
fn godbolt_example() {
let p2 = [42 as u8];
let p1 = [42 as u8];
unsafe {
printf(
"p1: %p, p2: %p\n\0" as *const str as *const i8,
transmute::<_, *const char>(&p1),
transmute::<_, *const char>(&p2),
)
}
let p1_ptr = usize_to_ptr(ptr_to_usize(unsafe { transmute::<_, *const i32>(&p1) }) + 1);
let p2_ptr = unsafe { transmute::<_, *const i32>(&p2) };
unsafe {
if p2_ptr == p1_ptr {
printf("1st attempt: pointers are equal\n\0" as *const str as *const i8)
} else {
printf("1st attempt: pointers are not equal\n\0" as *const str as *const i8)
}
if ptr_to_usize(p1_ptr) == ptr_to_usize(p2_ptr) {
printf("2nd attempt: pointers are equal\n\0" as *const str as *const i8)
} else {
printf("2nd attempt: pointers are not equal\n\0" as *const str as *const i8)
}
}
}
fn main() {
bugzilla_report();
godbolt_example();
}
Per a conversation I've had on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Rust.20Has.20Provenance.20RFC/near/420422460
Translating "bad but compliant with the C standard" C code into Rust shows that we have the same pointer semantics as the C language, while rustc differs greatly and has less undefined behavior in the example below. This is the proper Rust version, re-add commented out lines for the gccrs compatible one.
results: