Rollup merge of #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```
This commit is contained in:
commit
455a20b7ba
9 changed files with 104 additions and 21 deletions
63
library/core/src/const_closure.rs
Normal file
63
library/core/src/const_closure.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use crate::marker::Destruct;
|
||||
|
||||
/// Struct representing a closure with mutably borrowed data.
|
||||
///
|
||||
/// Example:
|
||||
/// ```no_build
|
||||
/// #![feature(const_mut_refs)]
|
||||
/// use crate::const_closure::ConstFnMutClosure;
|
||||
/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 {
|
||||
/// *state += arg;
|
||||
/// *state
|
||||
/// }
|
||||
/// let mut i = 5;
|
||||
/// let mut cl = ConstFnMutClosure::new(&mut i, imp);
|
||||
///
|
||||
/// assert!(7 == cl(2));
|
||||
/// assert!(8 == cl(1));
|
||||
/// ```
|
||||
pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> {
|
||||
data: &'a mut CapturedData,
|
||||
func: Function,
|
||||
}
|
||||
|
||||
impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> {
|
||||
/// Function for creating a new closure.
|
||||
///
|
||||
/// `data` is the a mutable borrow of data that is captured from the environment.
|
||||
///
|
||||
/// `func` is the function of the closure, it gets the data and a tuple of the arguments closure
|
||||
/// and return the return value of the closure.
|
||||
pub(crate) const fn new<ClosureArguments, ClosureReturnValue>(
|
||||
data: &'a mut CapturedData,
|
||||
func: Function,
|
||||
) -> Self
|
||||
where
|
||||
Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
|
||||
{
|
||||
Self { data, func }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const
|
||||
FnOnce<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function>
|
||||
where
|
||||
Function:
|
||||
~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct,
|
||||
{
|
||||
type Output = ClosureReturnValue;
|
||||
|
||||
extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
|
||||
self.call_mut(args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const
|
||||
FnMut<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function>
|
||||
where
|
||||
Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
|
||||
(self.func)(self.data, args)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
use crate::array;
|
||||
use crate::const_closure::ConstFnMutClosure;
|
||||
use crate::iter::{ByRefSized, FusedIterator, Iterator};
|
||||
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
|
||||
|
||||
|
@ -82,12 +83,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn fold<B, F>(mut self, init: B, f: F) -> B
|
||||
fn fold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
self.try_fold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,12 +127,12 @@ where
|
|||
try { acc }
|
||||
}
|
||||
|
||||
fn rfold<B, F>(mut self, init: B, f: F) -> B
|
||||
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
self.try_rfold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::ops::{NeverShortCircuit, Try};
|
||||
use crate::{
|
||||
const_closure::ConstFnMutClosure,
|
||||
ops::{NeverShortCircuit, Try},
|
||||
};
|
||||
|
||||
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
|
||||
///
|
||||
|
@ -36,12 +39,13 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<B, F>(self, init: B, f: F) -> B
|
||||
fn fold<B, F>(self, init: B, mut f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
// `fold` needs ownership, so this can't forward directly.
|
||||
I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
|
||||
.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -72,12 +76,17 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<B, F>(self, init: B, f: F) -> B
|
||||
fn rfold<B, F>(self, init: B, mut f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
// `rfold` needs ownership, so this can't forward directly.
|
||||
I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
|
||||
I::try_rfold(
|
||||
self.0,
|
||||
init,
|
||||
ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
|
||||
)
|
||||
.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::const_closure::ConstFnMutClosure;
|
||||
use crate::iter::{InPlaceIterable, Iterator};
|
||||
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};
|
||||
|
||||
|
@ -203,12 +204,12 @@ where
|
|||
.into_try()
|
||||
}
|
||||
|
||||
fn fold<B, F>(mut self, init: B, fold: F) -> B
|
||||
fn fold<B, F>(mut self, init: B, mut fold: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
|
||||
self.try_fold(init, ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp)).0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -356,6 +356,8 @@ mod bool;
|
|||
mod tuple;
|
||||
mod unit;
|
||||
|
||||
mod const_closure;
|
||||
|
||||
#[stable(feature = "core_primitive", since = "1.43.0")]
|
||||
pub mod primitive;
|
||||
|
||||
|
|
|
@ -126,7 +126,8 @@ impl<B, C> const ops::FromResidual for ControlFlow<B, C> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> {
|
||||
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
|
||||
impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> {
|
||||
type TryType = ControlFlow<B, C>;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ use crate::ops::ControlFlow;
|
|||
#[doc(alias = "?")]
|
||||
#[lang = "Try"]
|
||||
#[const_trait]
|
||||
pub trait Try: FromResidual {
|
||||
pub trait Try: ~const FromResidual {
|
||||
/// The type of the value produced by `?` when *not* short-circuiting.
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
type Output;
|
||||
|
@ -438,10 +438,11 @@ where
|
|||
/// and in the other direction,
|
||||
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
#[const_trait]
|
||||
pub trait Residual<O> {
|
||||
/// The "return" type of this meta-function.
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
type TryType: Try<Output = O, Residual = Self>;
|
||||
type TryType: ~const Try<Output = O, Residual = Self>;
|
||||
}
|
||||
|
||||
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
|
||||
|
@ -460,14 +461,17 @@ pub(crate) struct NeverShortCircuit<T>(pub T);
|
|||
impl<T> NeverShortCircuit<T> {
|
||||
/// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`.
|
||||
#[inline]
|
||||
pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
|
||||
move |a, b| NeverShortCircuit(f(a, b))
|
||||
pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
|
||||
f: &mut F,
|
||||
(a, b): (A, B),
|
||||
) -> NeverShortCircuit<T> {
|
||||
NeverShortCircuit(f(a, b))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum NeverShortCircuitResidual {}
|
||||
|
||||
impl<T> Try for NeverShortCircuit<T> {
|
||||
impl<T> const Try for NeverShortCircuit<T> {
|
||||
type Output = T;
|
||||
type Residual = NeverShortCircuitResidual;
|
||||
|
||||
|
@ -482,14 +486,14 @@ impl<T> Try for NeverShortCircuit<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> FromResidual for NeverShortCircuit<T> {
|
||||
impl<T> const FromResidual for NeverShortCircuit<T> {
|
||||
#[inline]
|
||||
fn from_residual(never: NeverShortCircuitResidual) -> Self {
|
||||
match never {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Residual<T> for NeverShortCircuitResidual {
|
||||
impl<T> const Residual<T> for NeverShortCircuitResidual {
|
||||
type TryType = NeverShortCircuit<T>;
|
||||
}
|
||||
|
||||
|
|
|
@ -2321,7 +2321,8 @@ impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
impl<T> ops::Residual<T> for Option<convert::Infallible> {
|
||||
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
|
||||
impl<T> const ops::Residual<T> for Option<convert::Infallible> {
|
||||
type TryType = Option<T>;
|
||||
}
|
||||
|
||||
|
|
|
@ -2116,6 +2116,7 @@ impl<T, E, F: From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> {
|
|||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||
impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> {
|
||||
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
|
||||
impl<T, E> const ops::Residual<T> for Result<convert::Infallible, E> {
|
||||
type TryType = Result<T, E>;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue