diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 8d4210c80827d..d2dc650910f63 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -1,3 +1,4 @@ +use super::char::EscapeDebugExtArgs; use super::from_utf8_unchecked; use super::validations::utf8_char_width; use crate::fmt; @@ -121,7 +122,11 @@ impl fmt::Debug for Debug<'_> { let valid = chunk.valid(); let mut from = 0; for (i, c) in valid.char_indices() { - let esc = c.escape_debug(); + let esc = c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: true, + escape_single_quote: false, + escape_double_quote: true, + }); // If char needs escaping, flush backlog so far and write, else skip if esc.len() != 1 { f.write_str(&valid[from..i])?; diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs index 11cd2b8776f22..fb816108351b0 100644 --- a/library/core/src/wtf8.rs +++ b/library/core/src/wtf8.rs @@ -19,7 +19,7 @@ // implementations, so, we'll have to add more doc(hidden)s anyway #![doc(hidden)] -use crate::char::{MAX_LEN_UTF16, encode_utf16_raw}; +use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF16, encode_utf16_raw}; use crate::clone::CloneToUninit; use crate::fmt::{self, Write}; use crate::hash::{Hash, Hasher}; @@ -144,14 +144,20 @@ impl AsRef<[u8]> for Wtf8 { impl fmt::Debug for Wtf8 { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { - use crate::fmt::Write; - for c in s.chars().flat_map(|c| c.escape_debug()) { + use crate::fmt::Write as _; + for c in s.chars().flat_map(|c| { + c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: true, + escape_single_quote: false, + escape_double_quote: true, + }) + }) { f.write_char(c)? } Ok(()) } - formatter.write_str("\"")?; + formatter.write_char('"')?; let mut pos = 0; while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) { // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes. @@ -164,7 +170,7 @@ impl fmt::Debug for Wtf8 { // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8. write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?; - formatter.write_str("\"") + formatter.write_char('"') } } diff --git a/library/coretests/tests/str_lossy.rs b/library/coretests/tests/str_lossy.rs index 6e70ea3e28574..820da38dd7466 100644 --- a/library/coretests/tests/str_lossy.rs +++ b/library/coretests/tests/str_lossy.rs @@ -80,4 +80,5 @@ fn debug() { b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa".utf8_chunks().debug(), ), ); + assert_eq!("\"'\"", &format!("{:?}", b"'".utf8_chunks().debug())); } diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 6d716bd854433..fd662e8a663a9 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -170,7 +170,7 @@ impl Iterator for Vars { impl fmt::Debug for Vars { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { inner: VarsOs { inner } } = self; - f.debug_struct("Vars").field("inner", &inner.str_debug()).finish() + f.debug_struct("Vars").field("inner", inner).finish() } } diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs index 2572b71fd9ac6..3474f0ab50684 100644 --- a/library/std/src/ffi/os_str/tests.rs +++ b/library/std/src/ffi/os_str/tests.rs @@ -303,3 +303,9 @@ fn clone_to_uninit() { unsafe { a.clone_to_uninit(ptr::from_mut::(&mut b).cast()) }; assert_eq!(a, &*b); } + +#[test] +fn debug() { + let s = "'single quotes'"; + assert_eq!(format!("{:?}", OsStr::new(s)), format!("{:?}", s)); +} diff --git a/library/std/src/sys/env/common.rs b/library/std/src/sys/env/common.rs index f161ff073f3d5..87e86e2947fad 100644 --- a/library/std/src/sys/env/common.rs +++ b/library/std/src/sys/env/common.rs @@ -5,27 +5,10 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list() - .entries(self.slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - impl Env { pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self { Env { iter: env.into_iter() } } - - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - EnvStrDebug { slice: self.iter.as_slice() } - } } impl fmt::Debug for Env { diff --git a/library/std/src/sys/env/unsupported.rs b/library/std/src/sys/env/unsupported.rs index 98905e6482747..a967ace95f02a 100644 --- a/library/std/src/sys/env/unsupported.rs +++ b/library/std/src/sys/env/unsupported.rs @@ -3,13 +3,6 @@ use crate::{fmt, io}; pub struct Env(!); -impl Env { - // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - self.0 - } -} - impl fmt::Debug for Env { fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { self.0 diff --git a/library/std/src/sys/env/windows.rs b/library/std/src/sys/env/windows.rs index 3c4d4a84cfd6b..219fcc4fb43f9 100644 --- a/library/std/src/sys/env/windows.rs +++ b/library/std/src/sys/env/windows.rs @@ -8,30 +8,6 @@ pub struct Env { iter: EnvIterator, } -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - iter: &'a EnvIterator, -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - let iter: EnvIterator = (*iter).clone(); - let mut list = f.debug_list(); - for (a, b) in iter { - list.entry(&(a.to_str().unwrap(), b.to_str().unwrap())); - } - list.finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { base: _, iter } = self; - EnvStrDebug { iter } - } -} - impl fmt::Debug for Env { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { base: _, iter } = self;