about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-02-03 14:15:22 -0800
committerGitHub <noreply@github.com>2023-02-03 14:15:22 -0800
commite99e05d13592d2e9868fa69f98dc01f9766f05ed (patch)
treefaa84e1df772ee6c48b73321bf6ba08931a456ef
parentbeb5cc9cf79b782094bb75fe41df3b7bdbb05bd7 (diff)
parentb886a4de157873c6a3e536a517fd6b097a4ab11b (diff)
downloadrust-e99e05d13592d2e9868fa69f98dc01f9766f05ed.tar.gz
rust-e99e05d13592d2e9868fa69f98dc01f9766f05ed.zip
Rollup merge of #107551 - fee1-dead-contrib:rm_const_fnmut_helper, r=oli-obk
 Replace `ConstFnMutClosure` with const closures

Also fixes a parser bug. cc `@oli-obk` for compiler changes
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs21
-rw-r--r--library/core/src/cmp.rs13
-rw-r--r--library/core/src/const_closure.rs78
-rw-r--r--library/core/src/iter/adapters/array_chunks.rs6
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs19
-rw-r--r--library/core/src/iter/mod.rs6
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/ops/try_trait.rs17
-rw-r--r--tests/ui/parser/recover-quantified-closure.rs2
-rw-r--r--tests/ui/parser/recover-quantified-closure.stderr4
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs10
12 files changed, 51 insertions, 129 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 8a6436b041b..28347b137f3 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2109,7 +2109,7 @@ impl<'a> Parser<'a> {
             ClosureBinder::NotPresent
         };
 
-        let constness = self.parse_constness(Case::Sensitive);
+        let constness = self.parse_closure_constness(Case::Sensitive);
 
         let movability =
             if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 2ea55f838a3..0cb88f3c3a9 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -732,9 +732,10 @@ impl<'a> Parser<'a> {
     fn check_const_closure(&self) -> bool {
         self.is_keyword_ahead(0, &[kw::Const])
             && self.look_ahead(1, |t| match &t.kind {
-                token::Ident(kw::Move | kw::Static | kw::Async, _)
-                | token::OrOr
-                | token::BinOp(token::Or) => true,
+                // async closures do not work with const closures, so we do not parse that here.
+                token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => {
+                    true
+                }
                 _ => false,
             })
     }
@@ -1198,8 +1199,18 @@ impl<'a> Parser<'a> {
 
     /// Parses constness: `const` or nothing.
     fn parse_constness(&mut self, case: Case) -> Const {
-        // Avoid const blocks to be parsed as const items
-        if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
+        self.parse_constness_(case, false)
+    }
+
+    /// Parses constness for closures
+    fn parse_closure_constness(&mut self, case: Case) -> Const {
+        self.parse_constness_(case, true)
+    }
+
+    fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
+        // Avoid const blocks and const closures to be parsed as const items
+        if (self.check_const_closure() == is_closure)
+            && self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
             && self.eat_keyword_case(kw::Const, case)
         {
             Const::Yes(self.prev_token.uninterpolated_span())
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index b75ae996e48..f290e5baf9d 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -22,7 +22,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::const_closure::ConstFnMutClosure;
 use crate::marker::Destruct;
 
 use self::Ordering::*;
@@ -1291,17 +1290,7 @@ where
     F: ~const Destruct,
     K: ~const Destruct,
 {
-    const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(
-        f: &mut F,
-        (v1, v2): (&T, &T),
-    ) -> Ordering
-    where
-        T: ~const Destruct,
-        K: ~const Destruct,
-    {
-        f(v1).cmp(&f(v2))
-    }
-    max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp))
+    max_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2)))
 }
 
 // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs
deleted file mode 100644
index 97900a4862f..00000000000
--- a/library/core/src/const_closure.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-use crate::marker::Destruct;
-use crate::marker::Tuple;
-
-/// 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<CapturedData, Function> {
-    /// 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 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.
-    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 }
-    }
-}
-
-macro_rules! impl_fn_mut_tuple {
-    ($($var:ident)*) => {
-        #[allow(unused_parens)]
-        impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
-            FnOnce<ClosureArguments> 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)
-            }
-        }
-        #[allow(unused_parens)]
-        impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
-            FnMut<ClosureArguments> 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/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs
index 5e4211058aa..af786609757 100644
--- a/library/core/src/iter/adapters/array_chunks.rs
+++ b/library/core/src/iter/adapters/array_chunks.rs
@@ -1,5 +1,4 @@
 use crate::array;
-use crate::const_closure::ConstFnMutClosure;
 use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce};
 use crate::mem::{self, MaybeUninit};
 use crate::ops::{ControlFlow, NeverShortCircuit, Try};
@@ -189,13 +188,12 @@ where
     I: Iterator,
 {
     #[inline]
-    default fn fold<B, F>(mut self, init: B, mut f: F) -> B
+    default fn fold<B, F>(mut self, init: B, f: F) -> B
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> B,
     {
-        let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp);
-        self.try_fold(init, fold).0
+        self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
     }
 }
 
diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs
index 1945e402ff5..477e7117c3e 100644
--- a/library/core/src/iter/adapters/by_ref_sized.rs
+++ b/library/core/src/iter/adapters/by_ref_sized.rs
@@ -1,7 +1,4 @@
-use crate::{
-    const_closure::ConstFnMutClosure,
-    ops::{NeverShortCircuit, Try},
-};
+use crate::ops::{NeverShortCircuit, Try};
 
 /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
 ///
@@ -39,13 +36,12 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
     }
 
     #[inline]
-    fn fold<B, F>(self, init: B, mut f: F) -> B
+    fn fold<B, F>(self, init: B, 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, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
-            .0
+        I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
     }
 
     #[inline]
@@ -76,17 +72,12 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
     }
 
     #[inline]
-    fn rfold<B, F>(self, init: B, mut f: F) -> B
+    fn rfold<B, F>(self, init: B, 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,
-            ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
-        )
-        .0
+        I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
     }
 
     #[inline]
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index bb35d50b4bf..00f57fbcc61 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -362,15 +362,13 @@ macro_rules! impl_fold_via_try_fold {
     };
     (@internal $fold:ident -> $try_fold:ident) => {
         #[inline]
-        fn $fold<AAA, FFF>(mut self, init: AAA, mut fold: FFF) -> AAA
+        fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
         where
             FFF: FnMut(AAA, Self::Item) -> AAA,
         {
-            use crate::const_closure::ConstFnMutClosure;
             use crate::ops::NeverShortCircuit;
 
-            let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp);
-            self.$try_fold(init, fold).0
+            self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
         }
     };
 }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 8961ef4ab48..dc0702c467a 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -376,8 +376,6 @@ mod bool;
 mod tuple;
 mod unit;
 
-mod const_closure;
-
 #[stable(feature = "core_primitive", since = "1.43.0")]
 pub mod primitive;
 
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 84a69046807..9108fc63045 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -379,13 +379,18 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
 pub(crate) struct NeverShortCircuit<T>(pub T);
 
 impl<T> NeverShortCircuit<T> {
-    /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
     #[inline]
-    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 fn wrap_mut_2<A, B>(
+        mut f: impl ~const FnMut(A, B) -> T,
+    ) -> impl ~const FnMut(A, B) -> Self {
+        cfg_if! {
+            if #[cfg(bootstrap)] {
+                #[allow(unused_parens)]
+                (const move |a, b| NeverShortCircuit(f(a, b)))
+            } else {
+                const move |a, b| NeverShortCircuit(f(a, b))
+            }
+        }
     }
 }
 
diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover-quantified-closure.rs
index df22f5e065c..10af39b7007 100644
--- a/tests/ui/parser/recover-quantified-closure.rs
+++ b/tests/ui/parser/recover-quantified-closure.rs
@@ -7,6 +7,6 @@ fn main() {
 enum Foo { Bar }
 fn foo(x: impl Iterator<Item = Foo>) {
     for <Foo>::Bar in x {}
-    //~^ ERROR expected one of `const`, `move`, `static`, `|`
+    //~^ ERROR expected one of `move`, `static`, `|`
     //~^^ ERROR `for<...>` binders for closures are experimental
 }
diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr
index 9ec4d2c034d..39eec80f658 100644
--- a/tests/ui/parser/recover-quantified-closure.stderr
+++ b/tests/ui/parser/recover-quantified-closure.stderr
@@ -1,8 +1,8 @@
-error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::`
+error: expected one of `move`, `static`, `|`, or `||`, found `::`
   --> $DIR/recover-quantified-closure.rs:9:14
    |
 LL |     for <Foo>::Bar in x {}
-   |              ^^ expected one of `const`, `move`, `static`, `|`, or `||`
+   |              ^^ expected one of `move`, `static`, `|`, or `||`
 
 error[E0658]: `for<...>` binders for closures are experimental
   --> $DIR/recover-quantified-closure.rs:2:5
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
new file mode 100644
index 00000000000..2c99d8bf1c6
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![feature(const_trait_impl, const_closures)]
+#![allow(incomplete_features)]
+
+const fn test() -> impl ~const Fn() {
+    const move || {}
+}
+
+fn main() {}