diff options
| author | Gabriel Bjørnager Jensen <gabriel@achernar.io> | 2024-11-21 12:16:00 +0100 |
|---|---|---|
| committer | Gabriel Bjørnager Jensen <gabriel@achernar.io> | 2024-11-21 12:27:18 +0100 |
| commit | 7c799c3e0d0c5e34126511467d62e1b654f41d3e (patch) | |
| tree | 7a4d7bf904ddd8ec4999a2929c772dd09cc69868 /library/core/src/array | |
| parent | 318f96a8cf3eca5c4aaf60a992f349bce5c3fd41 (diff) | |
| download | rust-7c799c3e0d0c5e34126511467d62e1b654f41d3e.tar.gz rust-7c799c3e0d0c5e34126511467d62e1b654f41d3e.zip | |
Mark and implement 'each_ref' and 'each_mut' in '[T; N]' as const;
Diffstat (limited to 'library/core/src/array')
| -rw-r--r-- | library/core/src/array/mod.rs | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 4764d7f0b0f..71dcab3423c 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -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. |
