@@ -358,6 +358,23 @@ fn align_offset_zst() {
358
358
}
359
359
}
360
360
361
+ #[ test]
362
+ #[ cfg( not( bootstrap) ) ]
363
+ fn align_offset_zst_const ( ) {
364
+ const {
365
+ // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
366
+ // all, because no amount of elements will align the pointer.
367
+ let mut p = 1 ;
368
+ while p < 1024 {
369
+ assert ! ( ptr:: invalid:: <( ) >( p) . align_offset( p) == 0 ) ;
370
+ if p != 1 {
371
+ assert ! ( ptr:: invalid:: <( ) >( p + 1 ) . align_offset( p) == !0 ) ;
372
+ }
373
+ p = ( p + 1 ) . next_power_of_two ( ) ;
374
+ }
375
+ }
376
+ }
377
+
361
378
#[ test]
362
379
fn align_offset_stride_one ( ) {
363
380
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
@@ -379,6 +396,26 @@ fn align_offset_stride_one() {
379
396
}
380
397
}
381
398
399
+ #[ test]
400
+ #[ cfg( not( bootstrap) ) ]
401
+ fn align_offset_stride_one_const ( ) {
402
+ const {
403
+ // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
404
+ // number of bytes.
405
+ let mut align = 1 ;
406
+ while align < 1024 {
407
+ let mut ptr = 1 ;
408
+ while ptr < 2 * align {
409
+ let expected = ptr % align;
410
+ let offset = if expected == 0 { 0 } else { align - expected } ;
411
+ assert ! ( ptr:: invalid:: <u8 >( ptr) . align_offset( align) == offset) ;
412
+ ptr += 1 ;
413
+ }
414
+ align = ( align + 1 ) . next_power_of_two ( ) ;
415
+ }
416
+ }
417
+ }
418
+
382
419
#[ test]
383
420
fn align_offset_various_strides ( ) {
384
421
unsafe fn test_stride < T > ( ptr : * const T , align : usize ) -> bool {
@@ -455,6 +492,134 @@ fn align_offset_various_strides() {
455
492
assert ! ( !x) ;
456
493
}
457
494
495
+ #[ test]
496
+ #[ cfg( not( bootstrap) ) ]
497
+ fn align_offset_various_strides_const ( ) {
498
+ const unsafe fn test_stride < T > ( ptr : * const T , numptr : usize , align : usize ) {
499
+ let mut expected = usize:: MAX ;
500
+ // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
501
+ let mut el = 0 ;
502
+ while el < align {
503
+ if ( numptr + el * :: std:: mem:: size_of :: < T > ( ) ) % align == 0 {
504
+ expected = el;
505
+ break ;
506
+ }
507
+ el += 1 ;
508
+ }
509
+ let got = ptr. align_offset ( align) ;
510
+ assert ! ( got == expected) ;
511
+ }
512
+
513
+ // For pointers of stride != 1, we verify the algorithm against the naivest possible
514
+ // implementation
515
+ let mut align = 1 ;
516
+ let limit = 1024 ;
517
+ while align < limit {
518
+ for ptr in 1usize ..4 * align {
519
+ unsafe {
520
+ #[ repr( packed) ]
521
+ struct A3 ( u16 , u8 ) ;
522
+ test_stride :: < A3 > ( ptr:: invalid :: < A3 > ( ptr) , ptr, align) ;
523
+
524
+ struct A4 ( u32 ) ;
525
+ test_stride :: < A4 > ( ptr:: invalid :: < A4 > ( ptr) , ptr, align) ;
526
+
527
+ #[ repr( packed) ]
528
+ struct A5 ( u32 , u8 ) ;
529
+ test_stride :: < A5 > ( ptr:: invalid :: < A5 > ( ptr) , ptr, align) ;
530
+
531
+ #[ repr( packed) ]
532
+ struct A6 ( u32 , u16 ) ;
533
+ test_stride :: < A6 > ( ptr:: invalid :: < A6 > ( ptr) , ptr, align) ;
534
+
535
+ #[ repr( packed) ]
536
+ struct A7 ( u32 , u16 , u8 ) ;
537
+ test_stride :: < A7 > ( ptr:: invalid :: < A7 > ( ptr) , ptr, align) ;
538
+
539
+ #[ repr( packed) ]
540
+ struct A8 ( u32 , u32 ) ;
541
+ test_stride :: < A8 > ( ptr:: invalid :: < A8 > ( ptr) , ptr, align) ;
542
+
543
+ #[ repr( packed) ]
544
+ struct A9 ( u32 , u32 , u8 ) ;
545
+ test_stride :: < A9 > ( ptr:: invalid :: < A9 > ( ptr) , ptr, align) ;
546
+
547
+ #[ repr( packed) ]
548
+ struct A10 ( u32 , u32 , u16 ) ;
549
+ test_stride :: < A10 > ( ptr:: invalid :: < A10 > ( ptr) , ptr, align) ;
550
+
551
+ test_stride :: < u32 > ( ptr:: invalid :: < u32 > ( ptr) , ptr, align) ;
552
+ test_stride :: < u128 > ( ptr:: invalid :: < u128 > ( ptr) , ptr, align) ;
553
+ }
554
+ }
555
+ align = ( align + 1 ) . next_power_of_two ( ) ;
556
+ }
557
+ }
558
+
559
+ #[ test]
560
+ #[ cfg( not( bootstrap) ) ]
561
+ fn align_offset_with_provenance_const ( ) {
562
+ const {
563
+ let data = 42 ;
564
+
565
+ let ptr: * const i32 = & data;
566
+ assert ! ( ptr. align_offset( 1 ) == 0 ) ;
567
+ assert ! ( ptr. align_offset( 2 ) == 0 ) ;
568
+ assert ! ( ptr. align_offset( 4 ) == 0 ) ;
569
+ assert ! ( ptr. align_offset( 8 ) == usize :: MAX ) ;
570
+ assert ! ( ptr. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
571
+ assert ! ( ptr. wrapping_byte_add( 1 ) . align_offset( 2 ) == usize :: MAX ) ;
572
+ assert ! ( ptr. wrapping_byte_add( 2 ) . align_offset( 1 ) == 0 ) ;
573
+ assert ! ( ptr. wrapping_byte_add( 2 ) . align_offset( 2 ) == 0 ) ;
574
+ assert ! ( ptr. wrapping_byte_add( 2 ) . align_offset( 4 ) == usize :: MAX ) ;
575
+ assert ! ( ptr. wrapping_byte_add( 3 ) . align_offset( 1 ) == 0 ) ;
576
+ assert ! ( ptr. wrapping_byte_add( 3 ) . align_offset( 2 ) == usize :: MAX ) ;
577
+
578
+ assert ! ( ptr. wrapping_add( 42 ) . align_offset( 4 ) == 0 ) ;
579
+ assert ! ( ptr. wrapping_add( 42 ) . align_offset( 8 ) == usize :: MAX ) ;
580
+
581
+ let ptr1: * const i8 = ptr. cast ( ) ;
582
+ assert ! ( ptr1. align_offset( 1 ) == 0 ) ;
583
+ assert ! ( ptr1. align_offset( 2 ) == 0 ) ;
584
+ assert ! ( ptr1. align_offset( 4 ) == 0 ) ;
585
+ assert ! ( ptr1. align_offset( 8 ) == usize :: MAX ) ;
586
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
587
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 2 ) == 1 ) ;
588
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 4 ) == 3 ) ;
589
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 8 ) == usize :: MAX ) ;
590
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 1 ) == 0 ) ;
591
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 2 ) == 0 ) ;
592
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 4 ) == 2 ) ;
593
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 8 ) == usize :: MAX ) ;
594
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 1 ) == 0 ) ;
595
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 2 ) == 1 ) ;
596
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 4 ) == 1 ) ;
597
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 8 ) == usize :: MAX ) ;
598
+
599
+ let ptr2: * const i16 = ptr. cast ( ) ;
600
+ assert ! ( ptr2. align_offset( 1 ) == 0 ) ;
601
+ assert ! ( ptr2. align_offset( 2 ) == 0 ) ;
602
+ assert ! ( ptr2. align_offset( 4 ) == 0 ) ;
603
+ assert ! ( ptr2. align_offset( 8 ) == usize :: MAX ) ;
604
+ assert ! ( ptr2. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
605
+ assert ! ( ptr2. wrapping_byte_add( 1 ) . align_offset( 2 ) == usize :: MAX ) ;
606
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 1 ) == 0 ) ;
607
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 2 ) == 0 ) ;
608
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 4 ) == 1 ) ;
609
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 8 ) == usize :: MAX ) ;
610
+ assert ! ( ptr2. wrapping_byte_add( 3 ) . align_offset( 1 ) == 0 ) ;
611
+ assert ! ( ptr2. wrapping_byte_add( 3 ) . align_offset( 2 ) == usize :: MAX ) ;
612
+
613
+ let ptr3: * const i64 = ptr. cast ( ) ;
614
+ assert ! ( ptr3. align_offset( 1 ) == 0 ) ;
615
+ assert ! ( ptr3. align_offset( 2 ) == 0 ) ;
616
+ assert ! ( ptr3. align_offset( 4 ) == 0 ) ;
617
+ assert ! ( ptr3. align_offset( 8 ) == usize :: MAX ) ;
618
+ assert ! ( ptr3. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
619
+ assert ! ( ptr3. wrapping_byte_add( 1 ) . align_offset( 2 ) == usize :: MAX ) ;
620
+ }
621
+ }
622
+
458
623
#[ test]
459
624
fn offset_from ( ) {
460
625
let mut a = [ 0 ; 5 ] ;
0 commit comments