Rollup merge of #133288 - bjoernager:const-array-each-ref, r=jhpratt

Support `each_ref` and `each_mut` in `[T; N]` in constant expressions.

Tracking issue: #133289

The methods `<[T; N]>::each_ref` and `<[T; N]>::each_mut` can easily be reimplemented to allow marking them with the `const` specifier.

This specific implementation takes a different approach than the original as to avoid using iterators (which are illegal in constant expressions).
This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-11-22 20:32:35 +08:00 committed by GitHub
commit 2e93a759a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -10,11 +10,13 @@ use crate::convert::Infallible;
use crate::error::Error;
use crate::fmt;
use crate::hash::{self, Hash};
use crate::intrinsics::transmute_unchecked;
use crate::iter::{UncheckedIterator, repeat_n};
use crate::mem::{self, MaybeUninit};
use crate::ops::{
ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
};
use crate::ptr::{null, null_mut};
use crate::slice::{Iter, IterMut};
mod ascii;
@ -606,8 +608,20 @@ impl<T, const N: usize> [T; N] {
/// assert_eq!(strings.len(), 3);
/// ```
#[stable(feature = "array_methods", since = "1.77.0")]
pub fn each_ref(&self) -> [&T; N] {
from_trusted_iterator(self.iter())
#[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")]
pub const fn each_ref(&self) -> [&T; N] {
let mut buf = [null::<T>(); N];
// FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
let mut i = 0;
while i < N {
buf[i] = &raw const self[i];
i += 1;
}
// SAFETY: `*const T` has the same layout as `&T`, and we've also initialised each pointer as a valid reference.
unsafe { transmute_unchecked(buf) }
}
/// Borrows each element mutably and returns an array of mutable references
@ -625,8 +639,20 @@ impl<T, const N: usize> [T; N] {
/// assert_eq!(floats, [0.0, 2.7, -1.0]);
/// ```
#[stable(feature = "array_methods", since = "1.77.0")]
pub fn each_mut(&mut self) -> [&mut T; N] {
from_trusted_iterator(self.iter_mut())
#[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")]
pub const fn each_mut(&mut self) -> [&mut T; N] {
let mut buf = [null_mut::<T>(); N];
// FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
let mut i = 0;
while i < N {
buf[i] = &raw mut self[i];
i += 1;
}
// SAFETY: `*mut T` has the same layout as `&mut T`, and we've also initialised each pointer as a valid reference.
unsafe { transmute_unchecked(buf) }
}
/// Divides one array reference into two at an index.