1- //@ build -pass
1+ //@ run -pass
22//@ revisions: normal randomize-layout
3- //@ [randomize-layout]compile-flags: -Zrandomize-layout
3+ //@ [randomize-layout]compile-flags: -Zrandomize-layout -Zlayout-seed=2
44
5- #![ crate_type = "lib" ]
5+ #![ feature ( offset_of_enum ) ]
66
7- struct Foo < T > ( u32 , T , u8 ) ;
7+ use std :: ptr ;
88
9- struct Wrapper < T > ( T ) ;
109
10+ // these types only have their field offsets taken, they're never constructed
11+ #[ allow( dead_code) ]
12+ pub struct Foo < T > ( u32 , T , u8 ) ;
13+ #[ allow( dead_code) ]
14+ pub struct Wrapper < T > ( T ) ;
1115#[ repr( transparent) ]
12- struct TransparentWrapper ( u16 ) ;
16+ #[ allow( dead_code) ]
17+ pub struct TransparentWrapper ( u16 ) ;
1318
1419const _: ( ) = {
15- // behavior of the current implementation, not guaranteed
20+ // Behavior of the current non-randomized implementation, not guaranteed
1621 #[ cfg( not( randomize_layout) ) ]
1722 assert ! ( std:: mem:: offset_of!( Foo :: <u16 >, 1 ) == std:: mem:: offset_of!( Foo :: <Wrapper <u16 >>, 1 ) ) ;
1823
@@ -21,10 +26,37 @@ const _: () = {
2126 assert ! ( std:: mem:: offset_of!( Foo :: <u16 >, 1 ) != std:: mem:: offset_of!( Foo :: <Wrapper <u16 >>, 1 ) ) ;
2227
2328 // Even transparent wrapper inner types get a different layout since associated type
24- // pecialization could result in the outer type behaving differently depending on the exact
29+ // specialization could result in the outer type behaving differently depending on the exact
2530 // inner type.
2631 #[ cfg( randomize_layout) ]
2732 assert ! (
2833 std:: mem:: offset_of!( Foo :: <u16 >, 1 ) != std:: mem:: offset_of!( Foo :: <TransparentWrapper >, 1 )
2934 ) ;
35+
36+ // Currently all fn pointers are treated interchangably even with randomization. Not guaranteed.
37+ // Associated type specialization could also break this.
38+ assert ! (
39+ std:: mem:: offset_of!( Foo :: <fn ( u32 ) >, 1 ) == std:: mem:: offset_of!( Foo :: <fn ( ) -> usize >, 1 )
40+ ) ;
41+
42+ // But subtype coercions must always result in the same layout.
43+ assert ! (
44+ std:: mem:: offset_of!( Foo :: <fn ( & u32 ) >, 1 ) == std:: mem:: offset_of!( Foo :: <fn ( & ' static u32 ) >, 1 )
45+ ) ;
46+
47+ // Randomization must uphold NPO guarantees
48+ assert ! ( std:: mem:: offset_of!( Option :: <& usize >, Some . 0 ) == 0 ) ;
49+ assert ! ( std:: mem:: offset_of!( Result :: <& usize , ( ) >, Ok . 0 ) == 0 ) ;
3050} ;
51+
52+ #[ allow( dead_code) ]
53+ struct Unsizable < T : ?Sized > ( usize , T ) ;
54+
55+ fn main ( ) {
56+ // offset_of doesn't let us probe the unsized field, check at runtime.
57+ let x = & Unsizable :: < [ u32 ; 4 ] > ( 0 , [ 0 ; 4 ] ) ;
58+ let y: & Unsizable :: < [ u32 ] > = x;
59+
60+ // type coercion must not change the layout.
61+ assert_eq ! ( ptr:: from_ref( & x. 1 ) . addr( ) , ptr:: from_ref( & y. 1 ) . addr( ) ) ;
62+ }
0 commit comments