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:
commit
2e93a759a3
1 changed files with 30 additions and 4 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue