Skip to content

Commit 25c44f4

Browse files
committed
Constified array::from_fn
1 parent 3ff4d56 commit 25c44f4

File tree

4 files changed

+31
-16
lines changed

4 files changed

+31
-16
lines changed

library/core/src/array/mod.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::error::Error;
1111
use crate::fmt;
1212
use crate::hash::{self, Hash};
1313
use crate::iter::UncheckedIterator;
14+
use crate::marker::Destruct;
1415
use crate::mem::{self, MaybeUninit};
1516
use crate::ops::{
1617
ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
@@ -55,9 +56,11 @@ pub use iter::IntoIter;
5556
/// ```
5657
#[inline]
5758
#[stable(feature = "array_from_fn", since = "1.63.0")]
58-
pub fn from_fn<T, const N: usize, F>(cb: F) -> [T; N]
59+
#[rustc_const_unstable(feature = "const_array_from_fn", issue = "none")]
60+
pub const fn from_fn<T, const N: usize, F>(cb: F) -> [T; N]
5961
where
60-
F: FnMut(usize) -> T,
62+
F: ~const FnMut(usize) -> T + ~const Destruct,
63+
T: ~const Destruct,
6164
{
6265
try_from_fn(NeverShortCircuit::wrap_mut_1(cb)).0
6366
}
@@ -93,11 +96,12 @@ where
9396
/// ```
9497
#[inline]
9598
#[unstable(feature = "array_try_from_fn", issue = "89379")]
96-
pub fn try_from_fn<R, const N: usize, F>(cb: F) -> ChangeOutputType<R, [R::Output; N]>
99+
pub const fn try_from_fn<R, const N: usize, F>(cb: F) -> ChangeOutputType<R, [R::Output; N]>
97100
where
98-
F: FnMut(usize) -> R,
99-
R: Try,
100-
R::Residual: Residual<[R::Output; N]>,
101+
F: ~const FnMut(usize) -> R + ~const Destruct,
102+
R: ~const Try,
103+
R::Residual: ~const Residual<[R::Output; N]>,
104+
R::Output: ~const Destruct,
101105
{
102106
let mut array = MaybeUninit::uninit_array::<N>();
103107
match try_from_fn_erased(&mut array, cb) {
@@ -835,12 +839,14 @@ where
835839
/// not optimizing away. So if you give it a shot, make sure to watch what
836840
/// happens in the codegen tests.
837841
#[inline]
838-
fn try_from_fn_erased<T, R>(
842+
#[rustc_const_unstable(feature = "const_array_from_fn", issue = "none")]
843+
const fn try_from_fn_erased<T, R>(
839844
buffer: &mut [MaybeUninit<T>],
840-
mut generator: impl FnMut(usize) -> R,
845+
mut generator: impl ~const FnMut(usize) -> R + ~const Destruct,
841846
) -> ControlFlow<R::Residual>
842847
where
843-
R: Try<Output = T>,
848+
R: ~const Try<Output = T>,
849+
R::Output: ~const Destruct,
844850
{
845851
let mut guard = Guard { array_mut: buffer, initialized: 0 };
846852

@@ -866,7 +872,7 @@ where
866872
///
867873
/// To minimize indirection fields are still pub but callers should at least use
868874
/// `push_unchecked` to signal that something unsafe is going on.
869-
struct Guard<'a, T> {
875+
struct Guard<'a, T: ~const Destruct> {
870876
/// The array to be initialized.
871877
pub array_mut: &'a mut [MaybeUninit<T>],
872878
/// The number of items that have been initialized so far.
@@ -880,7 +886,7 @@ impl<T> Guard<'_, T> {
880886
///
881887
/// No more than N elements must be initialized.
882888
#[inline]
883-
pub unsafe fn push_unchecked(&mut self, item: T) {
889+
pub const unsafe fn push_unchecked(&mut self, item: T) {
884890
// SAFETY: If `initialized` was correct before and the caller does not
885891
// invoke this method more than N times then writes will be in-bounds
886892
// and slots will not be initialized more than once.
@@ -891,7 +897,7 @@ impl<T> Guard<'_, T> {
891897
}
892898
}
893899

894-
impl<T> Drop for Guard<'_, T> {
900+
impl<T: ~const Destruct> const Drop for Guard<'_, T> {
895901
fn drop(&mut self) {
896902
debug_assert!(self.initialized <= self.array_mut.len());
897903

library/core/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
#![feature(const_align_of_val_raw)]
104104
#![feature(const_alloc_layout)]
105105
#![feature(const_arguments_as_str)]
106+
#![feature(const_array_from_fn)]
106107
#![feature(const_array_into_iter_constructors)]
107108
#![feature(const_bigint_helper_methods)]
108109
#![feature(const_black_box)]
@@ -112,6 +113,7 @@
112113
#![feature(const_clone)]
113114
#![feature(const_cmp)]
114115
#![feature(const_discriminant)]
116+
#![feature(const_drop_in_place)]
115117
#![feature(const_eval_select)]
116118
#![feature(const_exact_div)]
117119
#![feature(const_float_bits_conv)]
@@ -129,9 +131,11 @@
129131
#![feature(const_ipv6)]
130132
#![feature(const_iter)]
131133
#![feature(const_likely)]
132-
#![feature(const_maybe_uninit_uninit_array)]
134+
#![feature(const_maybe_uninit_array_assume_init)]
133135
#![feature(const_maybe_uninit_as_mut_ptr)]
134136
#![feature(const_maybe_uninit_assume_init)]
137+
#![feature(const_maybe_uninit_write)]
138+
#![feature(const_maybe_uninit_uninit_array)]
135139
#![feature(const_nonnull_new)]
136140
#![feature(const_num_from_num)]
137141
#![feature(const_ops)]

library/core/src/ops/try_trait.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::marker::Destruct;
12
use crate::ops::ControlFlow;
23

34
/// The `?` operator and `try {}` blocks.
@@ -384,8 +385,10 @@ impl<T> NeverShortCircuit<T> {
384385
/// This is useful for implementing infallible functions in terms of the `try_` ones,
385386
/// without accidentally capturing extra generic parameters in a closure.
386387
#[inline]
387-
pub fn wrap_mut_1<A>(mut f: impl FnMut(A) -> T) -> impl FnMut(A) -> NeverShortCircuit<T> {
388-
move |a| NeverShortCircuit(f(a))
388+
pub const fn wrap_mut_1<A>(
389+
mut f: impl ~const FnMut(A) -> T + ~const Destruct,
390+
) -> impl ~const FnMut(A) -> NeverShortCircuit<T> + ~const Destruct {
391+
const move |a| NeverShortCircuit(f(a))
389392
}
390393

391394
#[inline]

library/core/src/ptr/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ use crate::hash;
374374
use crate::intrinsics::{
375375
self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping,
376376
};
377+
use crate::marker::Destruct;
377378

378379
use crate::mem::{self, MaybeUninit};
379380

@@ -485,9 +486,10 @@ mod mut_ptr;
485486
/// assert!(weak.upgrade().is_none());
486487
/// ```
487488
#[stable(feature = "drop_in_place", since = "1.8.0")]
489+
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "none")]
488490
#[lang = "drop_in_place"]
489491
#[allow(unconditional_recursion)]
490-
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
492+
pub const unsafe fn drop_in_place<T: ?Sized + ~const Destruct>(to_drop: *mut T) {
491493
// Code here does not matter - this is replaced by the
492494
// real drop glue by the compiler.
493495

0 commit comments

Comments
 (0)