@@ -364,3 +364,193 @@ fn const_maybe_uninit() {
364
364
365
365
assert_eq ! ( FIELD_BY_FIELD , Foo { x: 1 , y: 2 } ) ;
366
366
}
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