Skip to content

Commit 4137088

Browse files
committed
Auto merge of #83079 - osa1:issue83046, r=m-ou-se
Update char::escape_debug_ext to handle different escapes in strings and chars Fixes #83046 The program fn main() { println!("{:?}", '"'); println!("{:?}", "'"); } would previously print '\"' "\'" With this patch it now prints: '"' "'"
2 parents 1316702 + 819247f commit 4137088

File tree

7 files changed

+54
-19
lines changed

7 files changed

+54
-19
lines changed

library/alloc/tests/fmt.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,7 @@ fn test_format_macro_interface() {
6868
t!(format!("{:?}", 10_usize), "10");
6969
t!(format!("{:?}", "true"), "\"true\"");
7070
t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
71-
t!(
72-
format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"),
73-
r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""#
74-
);
71+
t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#);
7572
t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#);
7673
t!(format!("{:o}", 10_usize), "12");
7774
t!(format!("{:x}", 10_usize), "a");

library/core/src/char/methods.rs

+29-6
Original file line numberDiff line numberDiff line change
@@ -403,16 +403,20 @@ impl char {
403403
}
404404

405405
/// An extended version of `escape_debug` that optionally permits escaping
406-
/// Extended Grapheme codepoints. This allows us to format characters like
407-
/// nonspacing marks better when they're at the start of a string.
406+
/// Extended Grapheme codepoints, single quotes, and double quotes. This
407+
/// allows us to format characters like nonspacing marks better when they're
408+
/// at the start of a string, and allows escaping single quotes in
409+
/// characters, and double quotes in strings.
408410
#[inline]
409-
pub(crate) fn escape_debug_ext(self, escape_grapheme_extended: bool) -> EscapeDebug {
411+
pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
410412
let init_state = match self {
411413
'\t' => EscapeDefaultState::Backslash('t'),
412414
'\r' => EscapeDefaultState::Backslash('r'),
413415
'\n' => EscapeDefaultState::Backslash('n'),
414-
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
415-
_ if escape_grapheme_extended && self.is_grapheme_extended() => {
416+
'\\' => EscapeDefaultState::Backslash(self),
417+
'"' if args.escape_double_quote => EscapeDefaultState::Backslash(self),
418+
'\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self),
419+
_ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
416420
EscapeDefaultState::Unicode(self.escape_unicode())
417421
}
418422
_ if is_printable(self) => EscapeDefaultState::Char(self),
@@ -458,7 +462,7 @@ impl char {
458462
#[stable(feature = "char_escape_debug", since = "1.20.0")]
459463
#[inline]
460464
pub fn escape_debug(self) -> EscapeDebug {
461-
self.escape_debug_ext(true)
465+
self.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)
462466
}
463467

464468
/// Returns an iterator that yields the literal escape code of a character
@@ -1565,6 +1569,25 @@ impl char {
15651569
}
15661570
}
15671571

1572+
pub(crate) struct EscapeDebugExtArgs {
1573+
/// Escape Extended Grapheme codepoints?
1574+
pub(crate) escape_grapheme_extended: bool,
1575+
1576+
/// Escape single quotes?
1577+
pub(crate) escape_single_quote: bool,
1578+
1579+
/// Escape double quotes?
1580+
pub(crate) escape_double_quote: bool,
1581+
}
1582+
1583+
impl EscapeDebugExtArgs {
1584+
pub(crate) const ESCAPE_ALL: Self = Self {
1585+
escape_grapheme_extended: true,
1586+
escape_single_quote: true,
1587+
escape_double_quote: true,
1588+
};
1589+
}
1590+
15681591
#[inline]
15691592
const fn len_utf8(code: u32) -> usize {
15701593
if code < MAX_ONE_B {

library/core/src/char/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub use self::methods::encode_utf8_raw;
4545
use crate::fmt::{self, Write};
4646
use crate::iter::FusedIterator;
4747

48+
pub(crate) use self::methods::EscapeDebugExtArgs;
49+
4850
// UTF-8 ranges and tags for encoding characters
4951
const TAG_CONT: u8 = 0b1000_0000;
5052
const TAG_TWO_B: u8 = 0b1100_0000;

library/core/src/fmt/mod.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![stable(feature = "rust1", since = "1.0.0")]
44

55
use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
6+
use crate::char::EscapeDebugExtArgs;
67
use crate::marker::PhantomData;
78
use crate::mem;
89
use crate::num::flt2dec;
@@ -2054,7 +2055,11 @@ impl Debug for str {
20542055
f.write_char('"')?;
20552056
let mut from = 0;
20562057
for (i, c) in self.char_indices() {
2057-
let esc = c.escape_debug();
2058+
let esc = c.escape_debug_ext(EscapeDebugExtArgs {
2059+
escape_grapheme_extended: true,
2060+
escape_single_quote: false,
2061+
escape_double_quote: true,
2062+
});
20582063
// If char needs escaping, flush backlog so far and write, else skip
20592064
if esc.len() != 1 {
20602065
f.write_str(&self[from..i])?;
@@ -2080,7 +2085,11 @@ impl Display for str {
20802085
impl Debug for char {
20812086
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
20822087
f.write_char('\'')?;
2083-
for c in self.escape_debug() {
2088+
for c in self.escape_debug_ext(EscapeDebugExtArgs {
2089+
escape_grapheme_extended: true,
2090+
escape_single_quote: true,
2091+
escape_double_quote: false,
2092+
}) {
20842093
f.write_char(c)?
20852094
}
20862095
f.write_char('\'')

library/core/src/str/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod validations;
1515
use self::pattern::Pattern;
1616
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
1717

18-
use crate::char;
18+
use crate::char::{self, EscapeDebugExtArgs};
1919
use crate::mem;
2020
use crate::slice::{self, SliceIndex};
2121

@@ -2342,7 +2342,7 @@ impl str {
23422342
EscapeDebug {
23432343
inner: chars
23442344
.next()
2345-
.map(|first| first.escape_debug_ext(true))
2345+
.map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
23462346
.into_iter()
23472347
.flatten()
23482348
.chain(chars.flat_map(CharEscapeDebugContinue)),
@@ -2460,7 +2460,11 @@ impl_fn_for_zst! {
24602460

24612461
#[derive(Clone)]
24622462
struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug {
2463-
c.escape_debug_ext(false)
2463+
c.escape_debug_ext(EscapeDebugExtArgs {
2464+
escape_grapheme_extended: false,
2465+
escape_single_quote: true,
2466+
escape_double_quote: true
2467+
})
24642468
};
24652469

24662470
#[derive(Clone)]

src/test/rustdoc-ui/check-doc-alias-attr.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s
1010
LL | #[doc(alias = 0)]
1111
| ^^^^^^^^^
1212

13-
error: '\"' character isn't allowed in `#[doc(alias = "...")]`
13+
error: '"' character isn't allowed in `#[doc(alias = "...")]`
1414
--> $DIR/check-doc-alias-attr.rs:9:15
1515
|
1616
LL | #[doc(alias = "\"")]
@@ -60,7 +60,7 @@ error: `#[doc(alias("a"))]` expects string literals
6060
LL | #[doc(alias(0))]
6161
| ^
6262

63-
error: '\"' character isn't allowed in `#[doc(alias("..."))]`
63+
error: '"' character isn't allowed in `#[doc(alias("..."))]`
6464
--> $DIR/check-doc-alias-attr.rs:20:13
6565
|
6666
LL | #[doc(alias("\""))]

src/test/ui/rustdoc/check-doc-alias-attr.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s
1010
LL | #[doc(alias = 0)]
1111
| ^^^^^^^^^
1212

13-
error: '\"' character isn't allowed in `#[doc(alias = "...")]`
13+
error: '"' character isn't allowed in `#[doc(alias = "...")]`
1414
--> $DIR/check-doc-alias-attr.rs:9:15
1515
|
1616
LL | #[doc(alias = "\"")]
@@ -60,7 +60,7 @@ error: `#[doc(alias("a"))]` expects string literals
6060
LL | #[doc(alias(0))]
6161
| ^
6262

63-
error: '\"' character isn't allowed in `#[doc(alias("..."))]`
63+
error: '"' character isn't allowed in `#[doc(alias("..."))]`
6464
--> $DIR/check-doc-alias-attr.rs:20:13
6565
|
6666
LL | #[doc(alias("\""))]

0 commit comments

Comments
 (0)