@@ -364,3 +364,193 @@ fn const_maybe_uninit() {
364364
365365 assert_eq ! ( FIELD_BY_FIELD , Foo { x: 1 , y: 2 } ) ;
366366}
367+
368+ #[ test]
369+ #[ cfg( not( bootstrap) ) ]
370+ fn offset_of ( ) {
371+ #[ repr( C ) ]
372+ struct Foo {
373+ x : u8 ,
374+ y : u16 ,
375+ z : Bar ,
376+ }
377+
378+ #[ repr( C ) ]
379+ struct Bar ( u8 , u8 ) ;
380+
381+ assert_eq ! ( offset_of!( Foo , x) , 0 ) ;
382+ assert_eq ! ( offset_of!( Foo , y) , 2 ) ;
383+ assert_eq ! ( offset_of!( Foo , z. 0 ) , 4 ) ;
384+ assert_eq ! ( offset_of!( Foo , z. 1 ) , 5 ) ;
385+
386+ // Layout of tuples is unstable
387+ assert ! ( offset_of!( ( u8 , u16 ) , 0 ) <= size_of:: <( u8 , u16 ) >( ) - 1 ) ;
388+ assert ! ( offset_of!( ( u8 , u16 ) , 1 ) <= size_of:: <( u8 , u16 ) >( ) - 2 ) ;
389+ }
390+
391+ #[ test]
392+ #[ cfg( not( bootstrap) ) ]
393+ fn offset_of_union ( ) {
394+ #[ repr( C ) ]
395+ union Foo {
396+ x : u8 ,
397+ y : u16 ,
398+ z : Bar ,
399+ }
400+
401+ #[ repr( C ) ]
402+ #[ derive( Copy , Clone ) ]
403+ struct Bar ( u8 , u8 ) ;
404+
405+ assert_eq ! ( offset_of!( Foo , x) , 0 ) ;
406+ assert_eq ! ( offset_of!( Foo , y) , 0 ) ;
407+ assert_eq ! ( offset_of!( Foo , z. 0 ) , 0 ) ;
408+ assert_eq ! ( offset_of!( Foo , z. 1 ) , 1 ) ;
409+ }
410+
411+ #[ test]
412+ #[ cfg( not( bootstrap) ) ]
413+ fn offset_of_dst ( ) {
414+ #[ repr( C ) ]
415+ struct Alpha {
416+ x : u8 ,
417+ y : u16 ,
418+ z : [ u8 ] ,
419+ }
420+
421+ trait Trait { }
422+
423+ #[ repr( C ) ]
424+ struct Beta {
425+ x : u8 ,
426+ y : u16 ,
427+ z : dyn Trait ,
428+ }
429+
430+ extern "C" {
431+ type Extern ;
432+ }
433+
434+ #[ repr( C ) ]
435+ struct Gamma {
436+ x : u8 ,
437+ y : u16 ,
438+ z : Extern ,
439+ }
440+
441+ assert_eq ! ( offset_of!( Alpha , x) , 0 ) ;
442+ assert_eq ! ( offset_of!( Alpha , y) , 2 ) ;
443+
444+ assert_eq ! ( offset_of!( Beta , x) , 0 ) ;
445+ assert_eq ! ( offset_of!( Beta , y) , 2 ) ;
446+
447+ assert_eq ! ( offset_of!( Gamma , x) , 0 ) ;
448+ assert_eq ! ( offset_of!( Gamma , y) , 2 ) ;
449+ }
450+
451+ #[ test]
452+ #[ cfg( not( bootstrap) ) ]
453+ fn offset_of_packed ( ) {
454+ #[ repr( C , packed) ]
455+ struct Foo {
456+ x : u8 ,
457+ y : u16 ,
458+ }
459+
460+ assert_eq ! ( offset_of!( Foo , x) , 0 ) ;
461+ assert_eq ! ( offset_of!( Foo , y) , 1 ) ;
462+ }
463+
464+ #[ test]
465+ #[ cfg( not( bootstrap) ) ]
466+ fn offset_of_projection ( ) {
467+ #[ repr( C ) ]
468+ struct Foo {
469+ x : u8 ,
470+ y : u16 ,
471+ }
472+
473+ trait Projector {
474+ type Type ;
475+ }
476+
477+ impl Projector for ( ) {
478+ type Type = Foo ;
479+ }
480+
481+ assert_eq ! ( offset_of!( <( ) as Projector >:: Type , x) , 0 ) ;
482+ assert_eq ! ( offset_of!( <( ) as Projector >:: Type , y) , 2 ) ;
483+ }
484+
485+ #[ test]
486+ #[ cfg( not( bootstrap) ) ]
487+ fn offset_of_alias ( ) {
488+ #[ repr( C ) ]
489+ struct Foo {
490+ x : u8 ,
491+ y : u16 ,
492+ }
493+
494+ type Bar = Foo ;
495+
496+ assert_eq ! ( offset_of!( Bar , x) , 0 ) ;
497+ assert_eq ! ( offset_of!( Bar , y) , 2 ) ;
498+ }
499+
500+ #[ test]
501+ #[ cfg( not( bootstrap) ) ]
502+ fn const_offset_of ( ) {
503+ #[ repr( C ) ]
504+ struct Foo {
505+ x : u8 ,
506+ y : u16 ,
507+ }
508+
509+ const X_OFFSET : usize = offset_of ! ( Foo , x) ;
510+ const Y_OFFSET : usize = offset_of ! ( Foo , y) ;
511+
512+ assert_eq ! ( X_OFFSET , 0 ) ;
513+ assert_eq ! ( Y_OFFSET , 2 ) ;
514+ }
515+
516+ #[ test]
517+ #[ cfg( not( bootstrap) ) ]
518+ fn offset_of_without_const_promotion ( ) {
519+ #[ repr( C ) ]
520+ struct Foo < SuppressConstPromotion > {
521+ x : u8 ,
522+ y : u16 ,
523+ _scp : SuppressConstPromotion ,
524+ }
525+
526+ // Normally, offset_of is always const promoted.
527+ // The generic parameter prevents this from happening.
528+ // This is needed to test the codegen impl of offset_of
529+ fn inner < SuppressConstPromotion > ( ) {
530+ assert_eq ! ( offset_of!( Foo <SuppressConstPromotion >, x) , 0 ) ;
531+ assert_eq ! ( offset_of!( Foo <SuppressConstPromotion >, y) , 2 ) ;
532+ }
533+
534+ inner :: < ( ) > ( ) ;
535+ }
536+
537+ #[ test]
538+ #[ cfg( not( bootstrap) ) ]
539+ fn offset_of_addr ( ) {
540+ #[ repr( C ) ]
541+ struct Foo {
542+ x : u8 ,
543+ y : u16 ,
544+ z : Bar ,
545+ }
546+
547+ #[ repr( C ) ]
548+ struct Bar ( u8 , u8 ) ;
549+
550+ let base = Foo { x : 0 , y : 0 , z : Bar ( 0 , 0 ) } ;
551+
552+ assert_eq ! ( ptr:: addr_of!( base) . addr( ) + offset_of!( Foo , x) , ptr:: addr_of!( base. x) . addr( ) ) ;
553+ assert_eq ! ( ptr:: addr_of!( base) . addr( ) + offset_of!( Foo , y) , ptr:: addr_of!( base. y) . addr( ) ) ;
554+ assert_eq ! ( ptr:: addr_of!( base) . addr( ) + offset_of!( Foo , z. 0 ) , ptr:: addr_of!( base. z. 0 ) . addr( ) ) ;
555+ assert_eq ! ( ptr:: addr_of!( base) . addr( ) + offset_of!( Foo , z. 1 ) , ptr:: addr_of!( base. z. 1 ) . addr( ) ) ;
556+ }
0 commit comments