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

Actually use TAIT instead of emulating it #125362

Merged
merged 2 commits into from
May 24, 2024
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
41 changes: 0 additions & 41 deletions library/core/src/internal_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,47 +80,6 @@ macro_rules! forward_ref_op_assign {
}
}

/// Create a zero-size type similar to a closure type, but named.
macro_rules! impl_fn_for_zst {
($(
$( #[$attr: meta] )*
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, )*))
}
}
)+
}
}

/// A macro for defining `#[cfg]` if-else statements.
///
/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@
#![feature(trait_alias)]
#![feature(transparent_unions)]
#![feature(try_blocks)]
#![feature(type_alias_impl_trait)]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
#![feature(with_negative_coherence)]
Expand Down
9 changes: 2 additions & 7 deletions library/core/src/slice/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl [u8] {
without modifying the original"]
#[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
pub fn escape_ascii(&self) -> EscapeAscii<'_> {
EscapeAscii { inner: self.iter().flat_map(EscapeByte) }
EscapeAscii { inner: self.iter().flat_map(|byte| byte.escape_ascii()) }
}

/// Returns a byte slice with leading ASCII whitespace bytes removed.
Expand Down Expand Up @@ -190,12 +190,7 @@ impl [u8] {
}
}

impl_fn_for_zst! {
#[derive(Clone)]
struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault {
ascii::escape_default(*byte)
};
}
type EscapeByte = impl (Fn(&u8) -> ascii::EscapeDefault) + Copy;

/// An iterator over the escaped version of a byte slice.
///
Expand Down
6 changes: 4 additions & 2 deletions library/core/src/str/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1274,8 +1274,10 @@ pub struct SplitWhitespace<'a> {
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct SplitAsciiWhitespace<'a> {
pub(super) inner:
Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
pub(super) inner: Map<
Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty<'a>>,
UnsafeBytesToStr<'a>,
>,
}

/// An iterator over the substrings of a string,
Expand Down
104 changes: 37 additions & 67 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ impl str {
#[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")]
#[inline]
pub fn split_whitespace(&self) -> SplitWhitespace<'_> {
SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
SplitWhitespace { inner: self.split(char::is_whitespace).filter(|s| !s.is_empty()) }
}

/// Splits a string slice by ASCII whitespace.
Expand Down Expand Up @@ -1032,8 +1032,13 @@ impl str {
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
#[inline]
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
let inner =
self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr);
let inner = self
.as_bytes()
.split(u8::is_ascii_whitespace)
.filter(|s| !s.is_empty())
// SAFETY: the byte slice came from a string and was only split
// along character boundaries, so the resulting slices are strings.
.map(|bytes| unsafe { from_utf8_unchecked(bytes) });
SplitAsciiWhitespace { inner }
}

Expand Down Expand Up @@ -1085,7 +1090,11 @@ impl str {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn lines(&self) -> Lines<'_> {
Lines(self.split_inclusive('\n').map(LinesMap))
Lines(self.split_inclusive('\n').map(|line| {
let Some(line) = line.strip_suffix('\n') else { return line };
let Some(line) = line.strip_suffix('\r') else { return line };
line
}))
}

/// An iterator over the lines of a string.
Expand Down Expand Up @@ -2636,14 +2645,19 @@ impl str {
#[stable(feature = "str_escape", since = "1.34.0")]
pub fn escape_debug(&self) -> EscapeDebug<'_> {
let mut chars = self.chars();
EscapeDebug {
inner: chars
.next()
.map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
.into_iter()
.flatten()
.chain(chars.flat_map(CharEscapeDebugContinue)),
}
let first = chars
.next()
.map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
.into_iter()
.flatten();
let inner = first.chain(chars.flat_map(|c| {
c.escape_debug_ext(EscapeDebugExtArgs {
escape_grapheme_extended: false,
escape_single_quote: true,
escape_double_quote: true,
})
}));
EscapeDebug { inner }
}

/// Return an iterator that escapes each char in `self` with [`char::escape_default`].
Expand Down Expand Up @@ -2681,7 +2695,7 @@ impl str {
without modifying the original"]
#[stable(feature = "str_escape", since = "1.34.0")]
pub fn escape_default(&self) -> EscapeDefault<'_> {
EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
EscapeDefault { inner: self.chars().flat_map(char::escape_default) }
}

/// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
Expand Down Expand Up @@ -2719,7 +2733,7 @@ impl str {
without modifying the original"]
#[stable(feature = "str_escape", since = "1.34.0")]
pub fn escape_unicode(&self) -> EscapeUnicode<'_> {
EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) }
EscapeUnicode { inner: self.chars().flat_map(char::escape_unicode) }
}
}

Expand Down Expand Up @@ -2750,59 +2764,15 @@ impl Default for &mut str {
}
}

impl_fn_for_zst! {
/// A nameable, cloneable fn type
#[derive(Clone)]
struct LinesMap impl<'a> Fn = |line: &'a str| -> &'a str {
let Some(line) = line.strip_suffix('\n') else { return line };
let Some(line) = line.strip_suffix('\r') else { return line };
line
};

#[derive(Clone)]
struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug {
c.escape_debug_ext(EscapeDebugExtArgs {
escape_grapheme_extended: false,
escape_single_quote: true,
escape_double_quote: true
})
};

#[derive(Clone)]
struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode {
c.escape_unicode()
};
#[derive(Clone)]
struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault {
c.escape_default()
};

#[derive(Clone)]
struct IsWhitespace impl Fn = |c: char| -> bool {
c.is_whitespace()
};

#[derive(Clone)]
struct IsAsciiWhitespace impl Fn = |byte: &u8| -> bool {
byte.is_ascii_whitespace()
};

#[derive(Clone)]
struct IsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b str| -> bool {
!s.is_empty()
};

#[derive(Clone)]
struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool {
!s.is_empty()
};

#[derive(Clone)]
struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
// SAFETY: not safe
unsafe { from_utf8_unchecked(bytes) }
};
}
type LinesMap = impl (Fn(&str) -> &str) + Copy;
type CharEscapeDebugContinue = impl (FnMut(char) -> char::EscapeDebug) + Copy;
type CharEscapeUnicode = impl (Fn(char) -> char::EscapeUnicode) + Copy;
type CharEscapeDefault = impl (Fn(char) -> char::EscapeDefault) + Copy;
type IsWhitespace = impl (Fn(char) -> bool) + Copy;
type IsAsciiWhitespace = impl (Fn(&u8) -> bool) + Copy;
type IsNotEmpty = impl (Fn(&&str) -> bool) + Copy;
type BytesIsNotEmpty<'a> = impl (FnMut(&&'a [u8]) -> bool) + Copy;
type UnsafeBytesToStr<'a> = impl (FnMut(&'a [u8]) -> &'a str) + Copy;

// This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap.
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
Loading