blob: ec5600ade16f1faad38293b625894630271c8dbb [file] [log] [blame]
//@ run-pass
// We need some non-1 alignment to test we use the alignment of the type in the compiler.
#[repr(align(4))]
struct Foo;
static FOO: Foo = Foo;
// This tests for regression of https://github.com/rust-lang/rust/issues/147516
//
// The compiler will codegen `&Zst` without creating a real allocation, just a properly aligned
// `usize` (i.e., ptr::dangling). However, code can add an arbitrary offset from that base
// allocation. We confirm here that we correctly codegen that offset combined with the necessary
// alignment of the base &() as a 1-ZST and &Foo as a 4-ZST.
const A: *const () = (&() as *const ()).wrapping_byte_add(2);
const B: *const () = (&Foo as *const _ as *const ()).wrapping_byte_add(usize::MAX);
const C: *const () = (&Foo as *const _ as *const ()).wrapping_byte_add(2);
fn main() {
// There's no stable guarantee that these are true.
// However, we want them to be true so that our LLVM IR and runtime are a bit faster:
// a constant address is cheap and doesn't result in relocations in comparison to a "real"
// global somewhere in the data section.
let x: &'static () = &();
assert_eq!(x as *const () as usize, 1);
let x: &'static Foo = &Foo;
assert_eq!(x as *const Foo as usize, 4);
// * A 1-aligned ZST (1-ZST) is placed at 0x1. Then offsetting that by 2 results in 3.
// * Foo is a 4-aligned ZST, so is placed at 0x4. +2 = 6
// * Foo is a 4-aligned ZST, so is placed at 0x4. +usize::MAX = -1 (same bit pattern) = 3
assert_eq!(A.addr(), 3);
assert_eq!(B.addr(), 3);
assert_eq!(C.addr(), 6);
// The exact addresses returned by these library functions are not necessarily stable guarantees
// but for now we assert that we're still matching.
#[allow(dangling_pointers_from_temporaries)]
{
assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
};
// statics must have a unique address (see https://github.com/rust-lang/rust/issues/18297, not
// clear whether this is a stable guarantee)
assert_ne!(&FOO as *const Foo as usize, 4);
}