Skip to content

Commit e556f44

Browse files
authored
Rollup merge of rust-lang#102186 - ink-feather-org:const_try_trait, r=fee1-dead
Add const_closure, Constify Try trait Adds a struct for creating const `FnMut` closures (for now just copy pasted form my [const_closure](https://crates.io/crates/const_closure) crate). I'm not sure if this way is how it should be done. The `ConstFnClosure` and `ConstFnOnceClosure` structs can probably also be entirely removed. This is then used to constify the try trait. Not sure if i should add const_closure in its own pr and maybe make it public behind a perma-unstable feature gate. cc ``@fee1-dead`` ``@rust-lang/wg-const-eval``
2 parents 6a92d4e + 84666af commit e556f44

File tree

9 files changed

+104
-21
lines changed

9 files changed

+104
-21
lines changed

library/core/src/const_closure.rs

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use crate::marker::Destruct;
2+
3+
/// Struct representing a closure with mutably borrowed data.
4+
///
5+
/// Example:
6+
/// ```no_build
7+
/// #![feature(const_mut_refs)]
8+
/// use crate::const_closure::ConstFnMutClosure;
9+
/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 {
10+
/// *state += arg;
11+
/// *state
12+
/// }
13+
/// let mut i = 5;
14+
/// let mut cl = ConstFnMutClosure::new(&mut i, imp);
15+
///
16+
/// assert!(7 == cl(2));
17+
/// assert!(8 == cl(1));
18+
/// ```
19+
pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> {
20+
data: &'a mut CapturedData,
21+
func: Function,
22+
}
23+
24+
impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> {
25+
/// Function for creating a new closure.
26+
///
27+
/// `data` is the a mutable borrow of data that is captured from the environment.
28+
///
29+
/// `func` is the function of the closure, it gets the data and a tuple of the arguments closure
30+
/// and return the return value of the closure.
31+
pub(crate) const fn new<ClosureArguments, ClosureReturnValue>(
32+
data: &'a mut CapturedData,
33+
func: Function,
34+
) -> Self
35+
where
36+
Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
37+
{
38+
Self { data, func }
39+
}
40+
}
41+
42+
impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const
43+
FnOnce<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function>
44+
where
45+
Function:
46+
~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct,
47+
{
48+
type Output = ClosureReturnValue;
49+
50+
extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
51+
self.call_mut(args)
52+
}
53+
}
54+
55+
impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const
56+
FnMut<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function>
57+
where
58+
Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
59+
{
60+
extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
61+
(self.func)(self.data, args)
62+
}
63+
}

library/core/src/iter/adapters/array_chunks.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::array;
2+
use crate::const_closure::ConstFnMutClosure;
23
use crate::iter::{ByRefSized, FusedIterator, Iterator};
34
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
45

@@ -82,12 +83,12 @@ where
8283
}
8384
}
8485

85-
fn fold<B, F>(mut self, init: B, f: F) -> B
86+
fn fold<B, F>(mut self, init: B, mut f: F) -> B
8687
where
8788
Self: Sized,
8889
F: FnMut(B, Self::Item) -> B,
8990
{
90-
self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
91+
self.try_fold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0
9192
}
9293
}
9394

@@ -126,12 +127,12 @@ where
126127
try { acc }
127128
}
128129

129-
fn rfold<B, F>(mut self, init: B, f: F) -> B
130+
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
130131
where
131132
Self: Sized,
132133
F: FnMut(B, Self::Item) -> B,
133134
{
134-
self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
135+
self.try_rfold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0
135136
}
136137
}
137138

library/core/src/iter/adapters/by_ref_sized.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::ops::{NeverShortCircuit, Try};
1+
use crate::{
2+
const_closure::ConstFnMutClosure,
3+
ops::{NeverShortCircuit, Try},
4+
};
25

36
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
47
///
@@ -36,12 +39,13 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
3639
}
3740

3841
#[inline]
39-
fn fold<B, F>(self, init: B, f: F) -> B
42+
fn fold<B, F>(self, init: B, mut f: F) -> B
4043
where
4144
F: FnMut(B, Self::Item) -> B,
4245
{
4346
// `fold` needs ownership, so this can't forward directly.
44-
I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
47+
I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
48+
.0
4549
}
4650

4751
#[inline]
@@ -72,12 +76,17 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
7276
}
7377

7478
#[inline]
75-
fn rfold<B, F>(self, init: B, f: F) -> B
79+
fn rfold<B, F>(self, init: B, mut f: F) -> B
7680
where
7781
F: FnMut(B, Self::Item) -> B,
7882
{
7983
// `rfold` needs ownership, so this can't forward directly.
80-
I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
84+
I::try_rfold(
85+
self.0,
86+
init,
87+
ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
88+
)
89+
.0
8190
}
8291

8392
#[inline]

library/core/src/iter/adapters/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::const_closure::ConstFnMutClosure;
12
use crate::iter::{InPlaceIterable, Iterator};
23
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};
34

@@ -203,12 +204,12 @@ where
203204
.into_try()
204205
}
205206

206-
fn fold<B, F>(mut self, init: B, fold: F) -> B
207+
fn fold<B, F>(mut self, init: B, mut fold: F) -> B
207208
where
208209
Self: Sized,
209210
F: FnMut(B, Self::Item) -> B,
210211
{
211-
self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
212+
self.try_fold(init, ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp)).0
212213
}
213214
}
214215

library/core/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ mod bool;
356356
mod tuple;
357357
mod unit;
358358

359+
mod const_closure;
360+
359361
#[stable(feature = "core_primitive", since = "1.43.0")]
360362
pub mod primitive;
361363

library/core/src/ops/control_flow.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ impl<B, C> const ops::FromResidual for ControlFlow<B, C> {
126126
}
127127

128128
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
129-
impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> {
129+
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
130+
impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> {
130131
type TryType = ControlFlow<B, C>;
131132
}
132133

library/core/src/ops/try_trait.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ use crate::ops::ControlFlow;
129129
#[doc(alias = "?")]
130130
#[lang = "Try"]
131131
#[const_trait]
132-
pub trait Try: FromResidual {
132+
pub trait Try: ~const FromResidual {
133133
/// The type of the value produced by `?` when *not* short-circuiting.
134134
#[unstable(feature = "try_trait_v2", issue = "84277")]
135135
type Output;
@@ -438,10 +438,11 @@ where
438438
/// and in the other direction,
439439
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
440440
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
441+
#[const_trait]
441442
pub trait Residual<O> {
442443
/// The "return" type of this meta-function.
443444
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
444-
type TryType: Try<Output = O, Residual = Self>;
445+
type TryType: ~const Try<Output = O, Residual = Self>;
445446
}
446447

447448
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
@@ -460,14 +461,17 @@ pub(crate) struct NeverShortCircuit<T>(pub T);
460461
impl<T> NeverShortCircuit<T> {
461462
/// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`.
462463
#[inline]
463-
pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
464-
move |a, b| NeverShortCircuit(f(a, b))
464+
pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
465+
f: &mut F,
466+
(a, b): (A, B),
467+
) -> NeverShortCircuit<T> {
468+
NeverShortCircuit(f(a, b))
465469
}
466470
}
467471

468472
pub(crate) enum NeverShortCircuitResidual {}
469473

470-
impl<T> Try for NeverShortCircuit<T> {
474+
impl<T> const Try for NeverShortCircuit<T> {
471475
type Output = T;
472476
type Residual = NeverShortCircuitResidual;
473477

@@ -482,14 +486,14 @@ impl<T> Try for NeverShortCircuit<T> {
482486
}
483487
}
484488

485-
impl<T> FromResidual for NeverShortCircuit<T> {
489+
impl<T> const FromResidual for NeverShortCircuit<T> {
486490
#[inline]
487491
fn from_residual(never: NeverShortCircuitResidual) -> Self {
488492
match never {}
489493
}
490494
}
491495

492-
impl<T> Residual<T> for NeverShortCircuitResidual {
496+
impl<T> const Residual<T> for NeverShortCircuitResidual {
493497
type TryType = NeverShortCircuit<T>;
494498
}
495499

library/core/src/option.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2321,7 +2321,8 @@ impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> {
23212321
}
23222322

23232323
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
2324-
impl<T> ops::Residual<T> for Option<convert::Infallible> {
2324+
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2325+
impl<T> const ops::Residual<T> for Option<convert::Infallible> {
23252326
type TryType = Option<T>;
23262327
}
23272328

library/core/src/result.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,7 @@ impl<T, E, F: From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> {
21162116
}
21172117

21182118
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
2119-
impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> {
2119+
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
2120+
impl<T, E> const ops::Residual<T> for Result<convert::Infallible, E> {
21202121
type TryType = Result<T, E>;
21212122
}

0 commit comments

Comments
 (0)