diff options
| author | The 8472 <git@infinite-source.de> | 2025-01-09 00:50:47 +0100 |
|---|---|---|
| committer | The 8472 <git@infinite-source.de> | 2025-01-10 02:22:57 +0100 |
| commit | d89b6d5ac6ceb7f735c8d2c7397fb6bb0e0e3020 (patch) | |
| tree | 5946e0a6442557851695ac0d9c6db484505627ee | |
| parent | 8b1de1682fcfaa2f56d6e4b98e1f18eb1bfcee55 (diff) | |
| download | rust-d89b6d5ac6ceb7f735c8d2c7397fb6bb0e0e3020.tar.gz rust-d89b6d5ac6ceb7f735c8d2c7397fb6bb0e0e3020.zip | |
test that coercions still work under randomization
| -rw-r--r-- | tests/ui/layout/randomize.rs | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/tests/ui/layout/randomize.rs b/tests/ui/layout/randomize.rs index da8414bc3e2..27e99327a31 100644 --- a/tests/ui/layout/randomize.rs +++ b/tests/ui/layout/randomize.rs @@ -1,18 +1,23 @@ -//@ build-pass +//@ run-pass //@ revisions: normal randomize-layout -//@ [randomize-layout]compile-flags: -Zrandomize-layout +//@ [randomize-layout]compile-flags: -Zrandomize-layout -Zlayout-seed=2 -#![crate_type = "lib"] +#![feature(offset_of_enum)] -struct Foo<T>(u32, T, u8); +use std::ptr; -struct Wrapper<T>(T); +// these types only have their field offsets taken, they're never constructed +#[allow(dead_code)] +pub struct Foo<T>(u32, T, u8); +#[allow(dead_code)] +pub struct Wrapper<T>(T); #[repr(transparent)] -struct TransparentWrapper(u16); +#[allow(dead_code)] +pub struct TransparentWrapper(u16); const _: () = { - // behavior of the current implementation, not guaranteed + // Behavior of the current non-randomized implementation, not guaranteed #[cfg(not(randomize_layout))] assert!(std::mem::offset_of!(Foo::<u16>, 1) == std::mem::offset_of!(Foo::<Wrapper<u16>>, 1)); @@ -21,10 +26,37 @@ const _: () = { assert!(std::mem::offset_of!(Foo::<u16>, 1) != std::mem::offset_of!(Foo::<Wrapper<u16>>, 1)); // Even transparent wrapper inner types get a different layout since associated type - // pecialization could result in the outer type behaving differently depending on the exact + // specialization could result in the outer type behaving differently depending on the exact // inner type. #[cfg(randomize_layout)] assert!( std::mem::offset_of!(Foo::<u16>, 1) != std::mem::offset_of!(Foo::<TransparentWrapper>, 1) ); + + // Currently all fn pointers are treated interchangably even with randomization. Not guaranteed. + // Associated type specialization could also break this. + assert!( + std::mem::offset_of!(Foo::<fn(u32)>, 1) == std::mem::offset_of!(Foo::<fn() -> usize>, 1) + ); + + // But subtype coercions must always result in the same layout. + assert!( + std::mem::offset_of!(Foo::<fn(&u32)>, 1) == std::mem::offset_of!(Foo::<fn(&'static u32)>, 1) + ); + + // Randomization must uphold NPO guarantees + assert!(std::mem::offset_of!(Option::<&usize>, Some.0) == 0); + assert!(std::mem::offset_of!(Result::<&usize, ()>, Ok.0) == 0); }; + +#[allow(dead_code)] +struct Unsizable<T: ?Sized>(usize, T); + +fn main() { + // offset_of doesn't let us probe the unsized field, check at runtime. + let x = &Unsizable::<[u32; 4]>(0, [0; 4]); + let y: &Unsizable::<[u32]> = x; + + // type coercion must not change the layout. + assert_eq!(ptr::from_ref(&x.1).addr(), ptr::from_ref(&y.1).addr()); +} |
