Skip to content

Commit 687d91b

Browse files
committed
[#224] Add crucible support for core::slice::as_chunks
This commit moves the allocate family of functions into core::crucible::alloc so that as_chunks_unchecked can call them.
1 parent 318f8c4 commit 687d91b

File tree

5 files changed

+58
-23
lines changed

5 files changed

+58
-23
lines changed

libs/Patches.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,13 @@ into the main commit for that patch, and then the *Update* line can be removed.
291291
* We use the Wasm configuration for the internal `guard::enable` function,
292292
which simply leaks everything.
293293

294+
* Avoid unsupported pointer-cast in `std::slice::as_chunks_unchecked` (last applied Feb 26, 2026)
295+
296+
Due to limitations of the current memory model we need to allocate a new
297+
array of arrays and then shallow-copy the original elements of the slice
298+
into those arrays. We note that this is unsound in the face of interior
299+
mutability.
300+
294301
# Notes
295302

296303
This section contains more detailed notes about why certain patches are written

libs/core/src/crucible/alloc.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![expect(unused_variables)]
2+
3+
/// Allocate an array of `len` elements of type `T`. The array begins uninitialized.
4+
pub fn allocate<T>(len: usize) -> *mut T {
5+
unimplemented!("allocate")
6+
}
7+
8+
/// Allocate an array of `len` elements of type `T`. The array initially contains all zeros. This
9+
/// fails if `crux-mir` doesn't know how to zero-initialize `T`.
10+
pub fn allocate_zeroed<T>(len: usize) -> *mut T {
11+
unimplemented!("allocate_zeroed")
12+
}
13+
14+
/// Reallocate the array at `*ptr` to contain `new_len` elements. This reallocation always happens
15+
/// in-place and never fails, so there is no need to return a new pointer.
16+
pub fn reallocate<T>(ptr: *mut T, new_len: usize) {
17+
unimplemented!("reallocate")
18+
}

libs/core/src/crucible/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ pub mod ptr;
88

99
#[unstable(feature = "crucible_intrinsics", issue = "none")]
1010
pub mod concurrency;
11+
12+
#[unstable(feature = "crucible_intrinsics", issue = "none")]
13+
pub mod alloc;

libs/core/src/slice/mod.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#![stable(feature = "rust1", since = "1.0.0")]
88

99
use 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};
1111
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
1212
use crate::num::NonZero;
1313
use 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) = 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,

libs/crucible/alloc.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,9 @@ use core::marker::PhantomData;
33
use core::mem;
44
use core::ptr::NonNull;
55

6-
/// Allocate an array of `len` elements of type `T`. The array begins uninitialized.
7-
pub fn allocate<T>(len: usize) -> *mut T {
8-
unimplemented!("allocate")
9-
}
10-
11-
/// Allocate an array of `len` elements of type `T`. The array initially contains all zeros. This
12-
/// fails if `crux-mir` doesn't know how to zero-initialize `T`.
13-
pub fn allocate_zeroed<T>(len: usize) -> *mut T {
14-
unimplemented!("allocate_zeroed")
15-
}
16-
17-
/// Reallocate the array at `*ptr` to contain `new_len` elements. This reallocation always happens
18-
/// in-place and never fails, so there is no need to return a new pointer.
19-
pub fn reallocate<T>(ptr: *mut T, new_len: usize) {
20-
unimplemented!("reallocate")
21-
}
22-
6+
pub use core::crucible::alloc::allocate;
7+
pub use core::crucible::alloc::allocate_zeroed;
8+
pub use core::crucible::alloc::reallocate;
239

2410
pub struct TypedAllocator<T>(pub PhantomData<T>);
2511

0 commit comments

Comments
 (0)