@@ -3474,44 +3474,13 @@ impl<T> [T] {
3474
3474
// Ts = size_of::<U> / gcd(size_of::<T>, size_of::<U>)
3475
3475
//
3476
3476
// Luckily since all this is constant-evaluated... performance here matters not!
3477
- #[ inline]
3478
- fn gcd ( a : usize , b : usize ) -> usize {
3479
- use crate :: intrinsics;
3480
- // iterative stein’s algorithm
3481
- // We should still make this `const fn` (and revert to recursive algorithm if we do)
3482
- // because relying on llvm to consteval all this is… well, it makes me uncomfortable.
3483
-
3484
- // SAFETY: `a` and `b` are checked to be non-zero values.
3485
- let ( ctz_a, mut ctz_b) = unsafe {
3486
- if a == 0 {
3487
- return b;
3488
- }
3489
- if b == 0 {
3490
- return a;
3491
- }
3492
- ( intrinsics:: cttz_nonzero ( a) , intrinsics:: cttz_nonzero ( b) )
3493
- } ;
3494
- let k = ctz_a. min ( ctz_b) ;
3495
- let mut a = a >> ctz_a;
3496
- let mut b = b;
3497
- loop {
3498
- // remove all factors of 2 from b
3499
- b >>= ctz_b;
3500
- if a > b {
3501
- mem:: swap ( & mut a, & mut b) ;
3502
- }
3503
- b = b - a;
3504
- // SAFETY: `b` is checked to be non-zero.
3505
- unsafe {
3506
- if b == 0 {
3507
- break ;
3508
- }
3509
- ctz_b = intrinsics:: cttz_nonzero ( b) ;
3510
- }
3511
- }
3512
- a << k
3477
+ const fn gcd ( a : usize , b : usize ) -> usize {
3478
+ if b == 0 { a } else { gcd ( b, a % b) }
3513
3479
}
3514
- let gcd: usize = gcd ( mem:: size_of :: < T > ( ) , mem:: size_of :: < U > ( ) ) ;
3480
+
3481
+ // Explicitly wrap the function call in a const block so it gets
3482
+ // constant-evaluated even in debug mode.
3483
+ let gcd: usize = const { gcd ( mem:: size_of :: < T > ( ) , mem:: size_of :: < U > ( ) ) } ;
3515
3484
let ts: usize = mem:: size_of :: < U > ( ) / gcd;
3516
3485
let us: usize = mem:: size_of :: < T > ( ) / gcd;
3517
3486
0 commit comments