77#![ stable( feature = "rust1" , since = "1.0.0" ) ]
88
99use crate :: cmp:: Ordering :: { self , Equal , Greater , Less } ;
10- use crate :: intrinsics:: { exact_div, unchecked_sub} ;
10+ use crate :: intrinsics:: { const_eval_select , exact_div, unchecked_sub} ;
1111use crate :: mem:: { self , MaybeUninit , SizedTypeProperties } ;
1212use crate :: num:: NonZero ;
1313use crate :: ops:: { OneSidedRange , OneSidedRangeBound , Range , RangeBounds , RangeInclusive } ;
@@ -1332,6 +1332,7 @@ impl<T> [T] {
13321332 /// ```
13331333 #[ stable( feature = "slice_as_chunks" , since = "1.88.0" ) ]
13341334 #[ rustc_const_stable( feature = "slice_as_chunks" , since = "1.88.0" ) ]
1335+ #[ rustc_allow_const_fn_unstable( const_eval_select) ]
13351336 #[ inline]
13361337 #[ must_use]
13371338 #[ track_caller]
@@ -1341,11 +1342,31 @@ impl<T> [T] {
13411342 "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks" ,
13421343 ( n: usize = N , len: usize = self . len( ) ) => n != 0 && len. is_multiple_of( n) ,
13431344 ) ;
1344- // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
1345- let new_len = unsafe { exact_div ( self . len ( ) , N ) } ;
1346- // SAFETY: We cast a slice of `new_len * N` elements into
1347- // a slice of `new_len` many `N` elements chunks.
1348- unsafe { from_raw_parts ( self . as_ptr ( ) . cast ( ) , new_len) }
1345+
1346+ const fn const_case < T , const N : usize > ( xs : & [ T ] ) -> & [ [ T ; N ] ] {
1347+ // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
1348+ let new_len = unsafe { exact_div ( xs. len ( ) , N ) } ;
1349+
1350+ // SAFETY: We cast a slice of `new_len * N` elements into
1351+ // a slice of `new_len` many `N` elements chunks.
1352+ unsafe { from_raw_parts ( xs. as_ptr ( ) . cast ( ) , new_len) }
1353+ }
1354+
1355+ // The non-const case needs to be able to call allocate which is not const fn
1356+ fn mut_case < T , const N : usize > ( xs : & [ T ] ) -> & [ [ T ; N ] ] {
1357+ // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
1358+ let new_len = unsafe { exact_div ( xs. len ( ) , N ) } ;
1359+
1360+ let ptr = crate :: crucible:: alloc:: allocate :: < [ T ; N ] > ( new_len) ;
1361+ for i in 0 ..new_len {
1362+ unsafe {
1363+ ptr. add ( i) . write ( crate :: array:: from_fn ( |j| xs. as_ptr ( ) . add ( N * i+j) . read ( ) ) ) ;
1364+ }
1365+ }
1366+ unsafe { from_raw_parts ( ptr, new_len) }
1367+ }
1368+
1369+ const_eval_select ( ( self , ) , const_case, mut_case)
13491370 }
13501371
13511372 /// Splits the slice into a slice of `N`-element arrays,
0 commit comments