Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add const_closure, Constify Try trait #102186

Merged
merged 6 commits into from
Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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> {
onestacked marked this conversation as resolved.
Show resolved Hide resolved
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>(
scottmcm marked this conversation as resolved.
Show resolved Hide resolved
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>;
}