Skip to content

Commit 17495e0

Browse files
authored
Rollup merge of #139656 - scottmcm:stabilize-slice-as-chunks, r=dtolnay
Stabilize `slice_as_chunks` library feature ~~Draft as this needs #139163 to land first.~~ FCP: #74985 (comment) Methods being stabilized are: ```rust impl [T] { const fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]); const fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]); const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]]; const fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]); const fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]); const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]]; } ``` ~~(FCP's not done quite yet, but will in another day if I'm counting right.)~~ FCP Complete: #74985 (comment)
2 parents d4845e1 + c49ddc0 commit 17495e0

File tree

6 files changed

+107
-27
lines changed

6 files changed

+107
-27
lines changed

compiler/rustc_span/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#![feature(round_char_boundary)]
3232
#![feature(rustc_attrs)]
3333
#![feature(rustdoc_internals)]
34-
#![feature(slice_as_chunks)]
3534
// tidy-alphabetical-end
3635

3736
// The code produced by the `Encodable`/`Decodable` derive macros refer to

library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@
118118
#![feature(ptr_metadata)]
119119
#![feature(set_ptr_value)]
120120
#![feature(slice_as_array)]
121-
#![feature(slice_as_chunks)]
122121
#![feature(slice_ptr_get)]
123122
#![feature(str_internals)]
124123
#![feature(str_split_inclusive_remainder)]

library/core/src/slice/iter.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2335,7 +2335,6 @@ pub struct ArrayChunks<'a, T: 'a, const N: usize> {
23352335

23362336
impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
23372337
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
2338-
// #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
23392338
#[inline]
23402339
pub(super) const fn new(slice: &'a [T]) -> Self {
23412340
let (array_slice, rem) = slice.as_chunks();

library/core/src/slice/mod.rs

+106-21
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,18 @@ impl<T> [T] {
12681268
/// Splits the slice into a slice of `N`-element arrays,
12691269
/// assuming that there's no remainder.
12701270
///
1271+
/// This is the inverse operation to [`as_flattened`].
1272+
///
1273+
/// [`as_flattened`]: slice::as_flattened
1274+
///
1275+
/// As this is `unsafe`, consider whether you could use [`as_chunks`] or
1276+
/// [`as_rchunks`] instead, perhaps via something like
1277+
/// `if let (chunks, []) = slice.as_chunks()` or
1278+
/// `let (chunks, []) = slice.as_chunks() else { unreachable!() };`.
1279+
///
1280+
/// [`as_chunks`]: slice::as_chunks
1281+
/// [`as_rchunks`]: slice::as_rchunks
1282+
///
12711283
/// # Safety
12721284
///
12731285
/// This may only be called when
@@ -1277,7 +1289,6 @@ impl<T> [T] {
12771289
/// # Examples
12781290
///
12791291
/// ```
1280-
/// #![feature(slice_as_chunks)]
12811292
/// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
12821293
/// let chunks: &[[char; 1]] =
12831294
/// // SAFETY: 1-element chunks never have remainder
@@ -1292,7 +1303,8 @@ impl<T> [T] {
12921303
/// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
12931304
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
12941305
/// ```
1295-
#[unstable(feature = "slice_as_chunks", issue = "74985")]
1306+
#[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
1307+
#[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
12961308
#[inline]
12971309
#[must_use]
12981310
pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
@@ -1312,15 +1324,27 @@ impl<T> [T] {
13121324
/// starting at the beginning of the slice,
13131325
/// and a remainder slice with length strictly less than `N`.
13141326
///
1327+
/// The remainder is meaningful in the division sense. Given
1328+
/// `let (chunks, remainder) = slice.as_chunks()`, then:
1329+
/// - `chunks.len()` equals `slice.len() / N`,
1330+
/// - `remainder.len()` equals `slice.len() % N`, and
1331+
/// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
1332+
///
1333+
/// You can flatten the chunks back into a slice-of-`T` with [`as_flattened`].
1334+
///
1335+
/// [`as_flattened`]: slice::as_flattened
1336+
///
13151337
/// # Panics
13161338
///
1317-
/// Panics if `N` is zero. This check will most probably get changed to a compile time
1318-
/// error before this method gets stabilized.
1339+
/// Panics if `N` is zero.
1340+
///
1341+
/// Note that this check is against a const generic parameter, not a runtime
1342+
/// value, and thus a particular monomorphization will either always panic
1343+
/// or it will never panic.
13191344
///
13201345
/// # Examples
13211346
///
13221347
/// ```
1323-
/// #![feature(slice_as_chunks)]
13241348
/// let slice = ['l', 'o', 'r', 'e', 'm'];
13251349
/// let (chunks, remainder) = slice.as_chunks();
13261350
/// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
@@ -1330,14 +1354,14 @@ impl<T> [T] {
13301354
/// If you expect the slice to be an exact multiple, you can combine
13311355
/// `let`-`else` with an empty slice pattern:
13321356
/// ```
1333-
/// #![feature(slice_as_chunks)]
13341357
/// let slice = ['R', 'u', 's', 't'];
13351358
/// let (chunks, []) = slice.as_chunks::<2>() else {
13361359
/// panic!("slice didn't have even length")
13371360
/// };
13381361
/// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
13391362
/// ```
1340-
#[unstable(feature = "slice_as_chunks", issue = "74985")]
1363+
#[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
1364+
#[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
13411365
#[inline]
13421366
#[track_caller]
13431367
#[must_use]
@@ -1357,21 +1381,34 @@ impl<T> [T] {
13571381
/// starting at the end of the slice,
13581382
/// and a remainder slice with length strictly less than `N`.
13591383
///
1384+
/// The remainder is meaningful in the division sense. Given
1385+
/// `let (remainder, chunks) = slice.as_rchunks()`, then:
1386+
/// - `remainder.len()` equals `slice.len() % N`,
1387+
/// - `chunks.len()` equals `slice.len() / N`, and
1388+
/// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
1389+
///
1390+
/// You can flatten the chunks back into a slice-of-`T` with [`as_flattened`].
1391+
///
1392+
/// [`as_flattened`]: slice::as_flattened
1393+
///
13601394
/// # Panics
13611395
///
1362-
/// Panics if `N` is zero. This check will most probably get changed to a compile time
1363-
/// error before this method gets stabilized.
1396+
/// Panics if `N` is zero.
1397+
///
1398+
/// Note that this check is against a const generic parameter, not a runtime
1399+
/// value, and thus a particular monomorphization will either always panic
1400+
/// or it will never panic.
13641401
///
13651402
/// # Examples
13661403
///
13671404
/// ```
1368-
/// #![feature(slice_as_chunks)]
13691405
/// let slice = ['l', 'o', 'r', 'e', 'm'];
13701406
/// let (remainder, chunks) = slice.as_rchunks();
13711407
/// assert_eq!(remainder, &['l']);
13721408
/// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
13731409
/// ```
1374-
#[unstable(feature = "slice_as_chunks", issue = "74985")]
1410+
#[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
1411+
#[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
13751412
#[inline]
13761413
#[track_caller]
13771414
#[must_use]
@@ -1424,6 +1461,18 @@ impl<T> [T] {
14241461
/// Splits the slice into a slice of `N`-element arrays,
14251462
/// assuming that there's no remainder.
14261463
///
1464+
/// This is the inverse operation to [`as_flattened_mut`].
1465+
///
1466+
/// [`as_flattened_mut`]: slice::as_flattened_mut
1467+
///
1468+
/// As this is `unsafe`, consider whether you could use [`as_chunks_mut`] or
1469+
/// [`as_rchunks_mut`] instead, perhaps via something like
1470+
/// `if let (chunks, []) = slice.as_chunks_mut()` or
1471+
/// `let (chunks, []) = slice.as_chunks_mut() else { unreachable!() };`.
1472+
///
1473+
/// [`as_chunks_mut`]: slice::as_chunks_mut
1474+
/// [`as_rchunks_mut`]: slice::as_rchunks_mut
1475+
///
14271476
/// # Safety
14281477
///
14291478
/// This may only be called when
@@ -1433,7 +1482,6 @@ impl<T> [T] {
14331482
/// # Examples
14341483
///
14351484
/// ```
1436-
/// #![feature(slice_as_chunks)]
14371485
/// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
14381486
/// let chunks: &mut [[char; 1]] =
14391487
/// // SAFETY: 1-element chunks never have remainder
@@ -1450,7 +1498,8 @@ impl<T> [T] {
14501498
/// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
14511499
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
14521500
/// ```
1453-
#[unstable(feature = "slice_as_chunks", issue = "74985")]
1501+
#[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
1502+
#[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
14541503
#[inline]
14551504
#[must_use]
14561505
pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
@@ -1470,15 +1519,27 @@ impl<T> [T] {
14701519
/// starting at the beginning of the slice,
14711520
/// and a remainder slice with length strictly less than `N`.
14721521
///
1522+
/// The remainder is meaningful in the division sense. Given
1523+
/// `let (chunks, remainder) = slice.as_chunks_mut()`, then:
1524+
/// - `chunks.len()` equals `slice.len() / N`,
1525+
/// - `remainder.len()` equals `slice.len() % N`, and
1526+
/// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
1527+
///
1528+
/// You can flatten the chunks back into a slice-of-`T` with [`as_flattened_mut`].
1529+
///
1530+
/// [`as_flattened_mut`]: slice::as_flattened_mut
1531+
///
14731532
/// # Panics
14741533
///
1475-
/// Panics if `N` is zero. This check will most probably get changed to a compile time
1476-
/// error before this method gets stabilized.
1534+
/// Panics if `N` is zero.
1535+
///
1536+
/// Note that this check is against a const generic parameter, not a runtime
1537+
/// value, and thus a particular monomorphization will either always panic
1538+
/// or it will never panic.
14771539
///
14781540
/// # Examples
14791541
///
14801542
/// ```
1481-
/// #![feature(slice_as_chunks)]
14821543
/// let v = &mut [0, 0, 0, 0, 0];
14831544
/// let mut count = 1;
14841545
///
@@ -1490,7 +1551,8 @@ impl<T> [T] {
14901551
/// }
14911552
/// assert_eq!(v, &[1, 1, 2, 2, 9]);
14921553
/// ```
1493-
#[unstable(feature = "slice_as_chunks", issue = "74985")]
1554+
#[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
1555+
#[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
14941556
#[inline]
14951557
#[track_caller]
14961558
#[must_use]
@@ -1510,15 +1572,27 @@ impl<T> [T] {
15101572
/// starting at the end of the slice,
15111573
/// and a remainder slice with length strictly less than `N`.
15121574
///
1575+
/// The remainder is meaningful in the division sense. Given
1576+
/// `let (remainder, chunks) = slice.as_rchunks_mut()`, then:
1577+
/// - `remainder.len()` equals `slice.len() % N`,
1578+
/// - `chunks.len()` equals `slice.len() / N`, and
1579+
/// - `slice.len()` equals `chunks.len() * N + remainder.len()`.
1580+
///
1581+
/// You can flatten the chunks back into a slice-of-`T` with [`as_flattened_mut`].
1582+
///
1583+
/// [`as_flattened_mut`]: slice::as_flattened_mut
1584+
///
15131585
/// # Panics
15141586
///
1515-
/// Panics if `N` is zero. This check will most probably get changed to a compile time
1516-
/// error before this method gets stabilized.
1587+
/// Panics if `N` is zero.
1588+
///
1589+
/// Note that this check is against a const generic parameter, not a runtime
1590+
/// value, and thus a particular monomorphization will either always panic
1591+
/// or it will never panic.
15171592
///
15181593
/// # Examples
15191594
///
15201595
/// ```
1521-
/// #![feature(slice_as_chunks)]
15221596
/// let v = &mut [0, 0, 0, 0, 0];
15231597
/// let mut count = 1;
15241598
///
@@ -1530,7 +1604,8 @@ impl<T> [T] {
15301604
/// }
15311605
/// assert_eq!(v, &[9, 1, 1, 2, 2]);
15321606
/// ```
1533-
#[unstable(feature = "slice_as_chunks", issue = "74985")]
1607+
#[stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
1608+
#[rustc_const_stable(feature = "slice_as_chunks", since = "CURRENT_RUSTC_VERSION")]
15341609
#[inline]
15351610
#[track_caller]
15361611
#[must_use]
@@ -4816,6 +4891,11 @@ impl<T> [MaybeUninit<T>] {
48164891
impl<T, const N: usize> [[T; N]] {
48174892
/// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
48184893
///
4894+
/// For the opposite operation, see [`as_chunks`] and [`as_rchunks`].
4895+
///
4896+
/// [`as_chunks`]: slice::as_chunks
4897+
/// [`as_rchunks`]: slice::as_rchunks
4898+
///
48194899
/// # Panics
48204900
///
48214901
/// This panics if the length of the resulting slice would overflow a `usize`.
@@ -4856,6 +4936,11 @@ impl<T, const N: usize> [[T; N]] {
48564936

48574937
/// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`.
48584938
///
4939+
/// For the opposite operation, see [`as_chunks_mut`] and [`as_rchunks_mut`].
4940+
///
4941+
/// [`as_chunks_mut`]: slice::as_chunks_mut
4942+
/// [`as_rchunks_mut`]: slice::as_rchunks_mut
4943+
///
48594944
/// # Panics
48604945
///
48614946
/// This panics if the length of the resulting slice would overflow a `usize`.

src/tools/miri/tests/pass/slices.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//@revisions: stack tree
22
//@[tree]compile-flags: -Zmiri-tree-borrows
33
//@compile-flags: -Zmiri-strict-provenance
4-
#![feature(slice_as_chunks)]
54
#![feature(slice_partition_dedup)]
65
#![feature(layout_for_ptr)]
76

@@ -227,7 +226,7 @@ fn test_for_invalidated_pointers() {
227226

228227
buffer.reverse();
229228

230-
// Calls `fn as_chunks_unchecked_mut` internally (requires unstable `#![feature(slice_as_chunks)]`):
229+
// Calls `fn as_chunks_unchecked_mut` internally:
231230
assert_eq!(2, buffer.as_chunks_mut::<32>().0.len());
232231
for chunk in buffer.as_chunks_mut::<32>().0 {
233232
for elem in chunk {

tests/codegen/slice-as_chunks.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//@ only-64bit (because the LLVM type of i64 for usize shows up)
33

44
#![crate_type = "lib"]
5-
#![feature(slice_as_chunks)]
65

76
// CHECK-LABEL: @chunks4
87
#[no_mangle]

0 commit comments

Comments
 (0)