Skip to content

Commit 0f949c2

Browse files
committed
Auto merge of #58051 - SimonSapin:str_escape, r=alexcrichton
Stabilize str::escape_* methods with new return types… … that implement `Display` and `Iterator<Item=char>`, as proposed in FCP: #27791 (comment)
2 parents b244f61 + eb158f9 commit 0f949c2

File tree

14 files changed

+326
-199
lines changed

14 files changed

+326
-199
lines changed

src/liballoc/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
#![warn(intra_doc_link_resolution_failure)]
6969
#![warn(missing_debug_implementations)]
7070

71-
#![cfg_attr(not(test), feature(fn_traits))]
7271
#![cfg_attr(not(test), feature(generator_trait))]
7372
#![cfg_attr(test, feature(test))]
7473

@@ -86,6 +85,7 @@
8685
#![feature(dropck_eyepatch)]
8786
#![feature(exact_size_is_empty)]
8887
#![feature(fmt_internals)]
88+
#![feature(fn_traits)]
8989
#![feature(fundamental)]
9090
#![feature(futures_api)]
9191
#![feature(lang_items)]
@@ -100,6 +100,7 @@
100100
#![feature(receiver_trait)]
101101
#![feature(specialization)]
102102
#![feature(staged_api)]
103+
#![feature(std_internals)]
103104
#![feature(str_internals)]
104105
#![feature(trusted_len)]
105106
#![feature(try_reserve)]

src/liballoc/str.rs

+1-41
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
#![allow(unused_imports)]
3030

3131
use core::borrow::Borrow;
32-
use core::fmt;
33-
use core::str as core_str;
3432
use core::str::pattern::{Pattern, Searcher, ReverseSearcher, DoubleEndedSearcher};
3533
use core::mem;
3634
use core::ptr;
@@ -443,45 +441,6 @@ impl str {
443441
return s;
444442
}
445443

446-
/// Escapes each char in `s` with [`char::escape_debug`].
447-
///
448-
/// Note: only extended grapheme codepoints that begin the string will be
449-
/// escaped.
450-
///
451-
/// [`char::escape_debug`]: primitive.char.html#method.escape_debug
452-
#[unstable(feature = "str_escape",
453-
reason = "return type may change to be an iterator",
454-
issue = "27791")]
455-
pub fn escape_debug(&self) -> String {
456-
let mut string = String::with_capacity(self.len());
457-
let mut chars = self.chars();
458-
if let Some(first) = chars.next() {
459-
string.extend(first.escape_debug_ext(true))
460-
}
461-
string.extend(chars.flat_map(|c| c.escape_debug_ext(false)));
462-
string
463-
}
464-
465-
/// Escapes each char in `s` with [`char::escape_default`].
466-
///
467-
/// [`char::escape_default`]: primitive.char.html#method.escape_default
468-
#[unstable(feature = "str_escape",
469-
reason = "return type may change to be an iterator",
470-
issue = "27791")]
471-
pub fn escape_default(&self) -> String {
472-
self.chars().flat_map(|c| c.escape_default()).collect()
473-
}
474-
475-
/// Escapes each char in `s` with [`char::escape_unicode`].
476-
///
477-
/// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode
478-
#[unstable(feature = "str_escape",
479-
reason = "return type may change to be an iterator",
480-
issue = "27791")]
481-
pub fn escape_unicode(&self) -> String {
482-
self.chars().flat_map(|c| c.escape_unicode()).collect()
483-
}
484-
485444
/// Converts a [`Box<str>`] into a [`String`] without copying or allocating.
486445
///
487446
/// [`String`]: string/struct.String.html
@@ -612,3 +571,4 @@ impl str {
612571
pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
613572
Box::from_raw(Box::into_raw(v) as *mut str)
614573
}
574+

src/liballoc/tests/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#![feature(pattern)]
66
#![feature(repeat_generic_slice)]
77
#![feature(slice_sort_by_cached_key)]
8-
#![feature(str_escape)]
98
#![feature(try_reserve)]
109
#![feature(unboxed_closures)]
1110
#![feature(vecdeque_rotate)]

src/liballoc/tests/str.rs

+31-30
Original file line numberDiff line numberDiff line change
@@ -990,15 +990,15 @@ fn test_split_at_boundscheck() {
990990

991991
#[test]
992992
fn test_escape_unicode() {
993-
assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
994-
assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
995-
assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
996-
assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
997-
assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
998-
assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
999-
assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
1000-
assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
1001-
assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
993+
assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
994+
assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
995+
assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
996+
assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
997+
assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
998+
assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
999+
assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1000+
assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1001+
assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
10021002
}
10031003

10041004
#[test]
@@ -1009,31 +1009,32 @@ fn test_escape_debug() {
10091009
// they are escaped. However, when the character is unescaped (e.g., for
10101010
// printable characters), only a single backslash appears (as the character
10111011
// itself appears in the debug string).
1012-
assert_eq!("abc".escape_debug(), "abc");
1013-
assert_eq!("a c".escape_debug(), "a c");
1014-
assert_eq!("éèê".escape_debug(), "éèê");
1015-
assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
1016-
assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
1017-
assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
1018-
assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
1019-
assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
1020-
assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
1021-
assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
1022-
assert_eq!("\u{301}a\u{301}\u{e000}".escape_debug(), "\\u{301}a\u{301}\\u{e000}");
1012+
assert_eq!("abc".escape_debug().to_string(), "abc");
1013+
assert_eq!("a c".escape_debug().to_string(), "a c");
1014+
assert_eq!("éèê".escape_debug().to_string(), "éèê");
1015+
assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1016+
assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1017+
assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1018+
assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1019+
assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1020+
assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1021+
assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1022+
assert_eq!("\u{301}a\u{301}\u{e000}".escape_debug().to_string(),
1023+
"\\u{301}a\u{301}\\u{e000}");
10231024
}
10241025

10251026
#[test]
10261027
fn test_escape_default() {
1027-
assert_eq!("abc".escape_default(), "abc");
1028-
assert_eq!("a c".escape_default(), "a c");
1029-
assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
1030-
assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
1031-
assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
1032-
assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
1033-
assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
1034-
assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
1035-
assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
1036-
assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
1028+
assert_eq!("abc".escape_default().to_string(), "abc");
1029+
assert_eq!("a c".escape_default().to_string(), "a c");
1030+
assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1031+
assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1032+
assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1033+
assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1034+
assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1035+
assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1036+
assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1037+
assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
10371038
}
10381039

10391040
#[test]

src/libcore/char/methods.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,8 @@ impl char {
189189
/// An extended version of `escape_debug` that optionally permits escaping
190190
/// Extended Grapheme codepoints. This allows us to format characters like
191191
/// nonspacing marks better when they're at the start of a string.
192-
#[doc(hidden)]
193-
#[unstable(feature = "str_internals", issue = "0")]
194192
#[inline]
195-
pub fn escape_debug_ext(self, escape_grapheme_extended: bool) -> EscapeDebug {
193+
pub(crate) fn escape_debug_ext(self, escape_grapheme_extended: bool) -> EscapeDebug {
196194
let init_state = match self {
197195
'\t' => EscapeDefaultState::Backslash('t'),
198196
'\r' => EscapeDefaultState::Backslash('r'),

src/libcore/internal_macros.rs

+44
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,47 @@ macro_rules! forward_ref_op_assign {
7575
}
7676
}
7777
}
78+
79+
/// Create a zero-size type similar to a closure type, but named.
80+
#[unstable(feature = "std_internals", issue = "0")]
81+
macro_rules! impl_fn_for_zst {
82+
($(
83+
$( #[$attr: meta] )*
84+
// FIXME: when libcore is in the 2018 edition, use `?` repetition in
85+
// $( <$( $li : lifetime ),+> )?
86+
struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )* Fn =
87+
|$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
88+
$body: block;
89+
)+) => {
90+
$(
91+
$( #[$attr] )*
92+
struct $Name;
93+
94+
impl $( <$( $lifetime ),+> )* Fn<($( $ArgTy, )*)> for $Name {
95+
#[inline]
96+
extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
97+
$body
98+
}
99+
}
100+
101+
impl $( <$( $lifetime ),+> )* FnMut<($( $ArgTy, )*)> for $Name {
102+
#[inline]
103+
extern "rust-call" fn call_mut(
104+
&mut self,
105+
($( $arg, )*): ($( $ArgTy, )*)
106+
) -> $ReturnTy {
107+
Fn::call(&*self, ($( $arg, )*))
108+
}
109+
}
110+
111+
impl $( <$( $lifetime ),+> )* FnOnce<($( $ArgTy, )*)> for $Name {
112+
type Output = $ReturnTy;
113+
114+
#[inline]
115+
extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
116+
Fn::call(&self, ($( $arg, )*))
117+
}
118+
}
119+
)+
120+
}
121+
}

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#![feature(simd_ffi)]
9696
#![feature(specialization)]
9797
#![feature(staged_api)]
98+
#![feature(std_internals)]
9899
#![feature(stmt_expr_attributes)]
99100
#![feature(unboxed_closures)]
100101
#![feature(unsized_locals)]

0 commit comments

Comments
 (0)