Skip to content

Commit

Permalink
Rollup merge of rust-lang#102186 - ink-feather-org:const_try_trait, r…
Browse files Browse the repository at this point in the history
…=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`
  • Loading branch information
Dylan-DPC authored Sep 24, 2022
2 parents 40cbc08 + 84666af commit 77847ce
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 21 deletions.
63 changes: 63 additions & 0 deletions library/core/src/const_closure.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
9 changes: 5 additions & 4 deletions library/core/src/iter/adapters/array_chunks.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::array;
use crate::const_closure::ConstFnMutClosure;
use crate::iter::{ByRefSized, FusedIterator, Iterator};
use crate::ops::{ControlFlow, NeverShortCircuit, Try};

Expand Down Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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
}
}

Expand Down
19 changes: 14 additions & 5 deletions library/core/src/iter/adapters/by_ref_sized.rs
Original file line number Diff line number Diff line change
@@ -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.
///
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/iter/adapters/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::const_closure::ConstFnMutClosure;
use crate::iter::{InPlaceIterable, Iterator};
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};

Expand Down Expand Up @@ -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
}
}

Expand Down
2 changes: 2 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ mod bool;
mod tuple;
mod unit;

mod const_closure;

#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;

Expand Down
3 changes: 2 additions & 1 deletion library/core/src/ops/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}

Expand Down
18 changes: 11 additions & 7 deletions library/core/src/ops/try_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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")]
Expand All @@ -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;

Expand All @@ -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>;
}

Expand Down
3 changes: 2 additions & 1 deletion library/core/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}

Expand Down
3 changes: 2 additions & 1 deletion library/core/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}

0 comments on commit 77847ce

Please sign in to comment.