diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2019-02-01 12:43:29 +0100 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2019-02-12 09:55:20 +0100 |
| commit | 92dcae47425a9084b97680bc0327ac88353b8a68 (patch) | |
| tree | 749a35073c0079522982002ef09487a9d0fdf7ff | |
| parent | 75f9159009cd0814bd6b5c3bf6a5406de7c4fe8d (diff) | |
| download | rust-92dcae47425a9084b97680bc0327ac88353b8a68.tar.gz rust-92dcae47425a9084b97680bc0327ac88353b8a68.zip | |
Add internal impl_fn_for_zst macro for "named closure types"
| -rw-r--r-- | src/libcore/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcore/macros.rs | 46 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 141 |
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; |
