1
- //@ build -pass
1
+ //@ run -pass
2
2
//@ revisions: normal randomize-layout
3
- //@ [randomize-layout]compile-flags: -Zrandomize-layout
3
+ //@ [randomize-layout]compile-flags: -Zrandomize-layout -Zlayout-seed=2
4
4
5
- #![ crate_type = "lib" ]
5
+ #![ feature ( offset_of_enum ) ]
6
6
7
- struct Foo < T > ( u32 , T , u8 ) ;
7
+ use std :: ptr ;
8
8
9
- struct Wrapper < T > ( T ) ;
10
9
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 ) ;
11
15
#[ repr( transparent) ]
12
- struct TransparentWrapper ( u16 ) ;
16
+ #[ allow( dead_code) ]
17
+ pub struct TransparentWrapper ( u16 ) ;
13
18
14
19
const _: ( ) = {
15
- // behavior of the current implementation, not guaranteed
20
+ // Behavior of the current non-randomized implementation, not guaranteed
16
21
#[ cfg( not( randomize_layout) ) ]
17
22
assert ! ( std:: mem:: offset_of!( Foo :: <u16 >, 1 ) == std:: mem:: offset_of!( Foo :: <Wrapper <u16 >>, 1 ) ) ;
18
23
@@ -21,10 +26,37 @@ const _: () = {
21
26
assert ! ( std:: mem:: offset_of!( Foo :: <u16 >, 1 ) != std:: mem:: offset_of!( Foo :: <Wrapper <u16 >>, 1 ) ) ;
22
27
23
28
// 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
25
30
// inner type.
26
31
#[ cfg( randomize_layout) ]
27
32
assert ! (
28
33
std:: mem:: offset_of!( Foo :: <u16 >, 1 ) != std:: mem:: offset_of!( Foo :: <TransparentWrapper >, 1 )
29
34
) ;
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 ) ;
30
50
} ;
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