about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2019-02-01 12:43:29 +0100
committerSimon Sapin <simon.sapin@exyr.org>2019-02-12 09:55:20 +0100
commit92dcae47425a9084b97680bc0327ac88353b8a68 (patch)
tree749a35073c0079522982002ef09487a9d0fdf7ff
parent75f9159009cd0814bd6b5c3bf6a5406de7c4fe8d (diff)
downloadrust-92dcae47425a9084b97680bc0327ac88353b8a68.tar.gz
rust-92dcae47425a9084b97680bc0327ac88353b8a68.zip
Add internal impl_fn_for_zst macro for "named closure types"
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/macros.rs46
-rw-r--r--src/libcore/str/mod.rs141
3 files changed, 75 insertions, 113 deletions
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 8b728c9414d..419980225c3 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -95,6 +95,7 @@
 #![feature(simd_ffi)]
 #![feature(specialization)]
 #![feature(staged_api)]
+#![feature(std_internals)]
 #![feature(stmt_expr_attributes)]
 #![feature(unboxed_closures)]
 #![feature(unsized_locals)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 664490c1997..bc5d35f7191 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -749,3 +749,49 @@ mod builtin {
         ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
     }
 }
+
+/// Create a named zero-size type similar to a closure.
+#[doc(hidden)]
+#[macro_export]
+#[unstable(feature = "std_internals", issue = "0")]
+macro_rules! impl_fn_for_zst {
+    ($(
+        $( #[$attr: meta] )*
+        // FIXME: when libcore is in the 2018 edition, use `?` repetition in
+        // $( <$( $li : lifetime ),+> )?
+        struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )* Fn =
+            |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
+            $body: block;
+    )+) => {
+        $(
+            $( #[$attr] )*
+            struct $Name;
+
+            impl $( <$( $lifetime ),+> )* Fn<($( $ArgTy, )*)> for $Name {
+                #[inline]
+                extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
+                    $body
+                }
+            }
+
+            impl $( <$( $lifetime ),+> )* FnMut<($( $ArgTy, )*)> for $Name {
+                #[inline]
+                extern "rust-call" fn call_mut(
+                    &mut self,
+                    ($( $arg, )*): ($( $ArgTy, )*)
+                ) -> $ReturnTy {
+                    Fn::call(&*self, ($( $arg, )*))
+                }
+            }
+
+            impl $( <$( $lifetime ),+> )* FnOnce<($( $ArgTy, )*)> for $Name {
+                type Output = $ReturnTy;
+
+                #[inline]
+                extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
+                    Fn::call(&self, ($( $arg, )*))
+                }
+            }
+        )+
+    }
+}
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index e9190cc3ddf..eefed517330 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1345,33 +1345,14 @@ impl FusedIterator for Lines<'_> {}
 #[allow(deprecated)]
 pub struct LinesAny<'a>(Lines<'a>);
 
-/// A nameable, cloneable fn type
-#[derive(Clone)]
-struct LinesAnyMap;
-
-impl<'a> Fn<(&'a str,)> for LinesAnyMap {
-    #[inline]
-    extern "rust-call" fn call(&self, (line,): (&'a str,)) -> &'a str {
+impl_fn_for_zst! {
+    /// A nameable, cloneable fn type
+    #[derive(Clone)]
+    struct LinesAnyMap impl<'a> Fn = |line: &'a str| -> &'a str {
         let l = line.len();
         if l > 0 && line.as_bytes()[l - 1] == b'\r' { &line[0 .. l - 1] }
         else { line }
-    }
-}
-
-impl<'a> FnMut<(&'a str,)> for LinesAnyMap {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, (line,): (&'a str,)) -> &'a str {
-        Fn::call(&*self, (line,))
-    }
-}
-
-impl<'a> FnOnce<(&'a str,)> for LinesAnyMap {
-    type Output = &'a str;
-
-    #[inline]
-    extern "rust-call" fn call_once(self, (line,): (&'a str,)) -> &'a str {
-        Fn::call(&self, (line,))
-    }
+    };
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2727,7 +2708,7 @@ impl str {
         let inner = self
             .as_bytes()
             .split(IsAsciiWhitespace)
-            .filter(IsNotEmpty)
+            .filter(BytesIsNotEmpty)
             .map(UnsafeBytesToStr);
         SplitAsciiWhitespace { inner }
     }
@@ -4011,102 +3992,36 @@ pub struct SplitWhitespace<'a> {
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 #[derive(Clone, Debug)]
 pub struct SplitAsciiWhitespace<'a> {
-    inner: Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, IsNotEmpty>, UnsafeBytesToStr>,
-}
-
-#[derive(Clone)]
-struct IsWhitespace;
-
-impl FnOnce<(char, )> for IsWhitespace {
-    type Output = bool;
-
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
-        self.call_mut(arg)
-    }
+    inner: Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
 }
 
-impl FnMut<(char, )> for IsWhitespace {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
-        arg.0.is_whitespace()
-    }
-}
-
-#[derive(Clone)]
-struct IsAsciiWhitespace;
-
-impl<'a> FnOnce<(&'a u8, )> for IsAsciiWhitespace {
-    type Output = bool;
-
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&u8, )) -> bool {
-        self.call_mut(arg)
-    }
-}
-
-impl<'a> FnMut<(&'a u8, )> for IsAsciiWhitespace {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&u8, )) -> bool {
-        arg.0.is_ascii_whitespace()
-    }
-}
-
-#[derive(Clone)]
-struct IsNotEmpty;
-
-impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
-    type Output = bool;
-
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&'a &'b str, )) -> bool {
-        self.call_mut(arg)
-    }
-}
-
-impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b str, )) -> bool {
-        !arg.0.is_empty()
-    }
-}
-
-impl<'a, 'b> FnOnce<(&'a &'b [u8], )> for IsNotEmpty {
-    type Output = bool;
-
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&'a &'b [u8], )) -> bool {
-        self.call_mut(arg)
-    }
-}
-
-impl<'a, 'b> FnMut<(&'a &'b [u8], )> for IsNotEmpty {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b [u8], )) -> bool {
-        !arg.0.is_empty()
-    }
-}
+impl_fn_for_zst! {
+    #[derive(Clone)]
+    struct IsWhitespace impl Fn = |c: char| -> bool {
+        c.is_whitespace()
+    };
 
-#[derive(Clone)]
-struct UnsafeBytesToStr;
+    #[derive(Clone)]
+    struct IsAsciiWhitespace impl Fn = |byte: &u8| -> bool {
+        byte.is_ascii_whitespace()
+    };
 
-impl<'a> FnOnce<(&'a [u8], )> for UnsafeBytesToStr {
-    type Output = &'a str;
+    #[derive(Clone)]
+    struct IsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b str| -> bool {
+        !s.is_empty()
+    };
 
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&'a [u8], )) -> &'a str {
-        self.call_mut(arg)
-    }
-}
+    #[derive(Clone)]
+    struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool {
+        !s.is_empty()
+    };
 
-impl<'a> FnMut<(&'a [u8], )> for UnsafeBytesToStr {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&'a [u8], )) -> &'a str {
-        unsafe { from_utf8_unchecked(arg.0) }
-    }
+    #[derive(Clone)]
+    struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
+        unsafe { from_utf8_unchecked(bytes) }
+    };
 }
 
-
 #[stable(feature = "split_whitespace", since = "1.1.0")]
 impl<'a> Iterator for SplitWhitespace<'a> {
     type Item = &'a str;