diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index d2e80e8e7e5df..9e9c02093be20 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -16,15 +16,18 @@ use crate::marker::Destruct; /// assert!(7 == cl(2)); /// assert!(8 == cl(1)); /// ``` -pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> { - data: &'a mut CapturedData, - func: Function, +pub(crate) struct ConstFnMutClosure { + /// The Data captured by the Closure. + /// Must be either a (mutable) reference or a tuple of (mutable) references. + pub data: CapturedData, + /// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn + pub func: Function, } - -impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> { +impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> { /// Function for creating a new closure. /// /// `data` is the a mutable borrow of data that is captured from the environment. + /// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually. /// /// `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. @@ -39,25 +42,36 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Fun } } -impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const - FnOnce for ConstFnMutClosure<'a, CapturedData, Function> -where - Function: - ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, -{ - type Output = ClosureReturnValue; +macro_rules! impl_fn_mut_tuple { + ($($var:ident)*) => { + #[allow(unused_parens)] + impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const + FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), 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 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) - } + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } + } + #[allow(unused_parens)] + impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const + FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, + { + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + #[allow(non_snake_case)] + let ($($var),*) = &mut self.data; + (self.func)(($($var),*), args) + } + } + }; } +impl_fn_mut_tuple!(A); +impl_fn_mut_tuple!(A B); +impl_fn_mut_tuple!(A B C); +impl_fn_mut_tuple!(A B C D); +impl_fn_mut_tuple!(A B C D E); diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 33df9e6c5cd48..84a69046807c4 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -379,7 +379,7 @@ pub(crate) type ChangeOutputType = <::Residual as Residual>:: pub(crate) struct NeverShortCircuit(pub T); impl NeverShortCircuit { - /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. + /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`. #[inline] pub const fn wrap_mut_2_imp T>( f: &mut F,