Skip to content

Commit 0f1da7e

Browse files
authored
Rollup merge of #117730 - jmillikin:fmt-debug-helper-fns, r=cuviper
Closure-consuming helper functions for `fmt::Debug` helpers ACP: rust-lang/libs-team#288 Tracking issue: #117729
2 parents 7096ec3 + 82a9f94 commit 0f1da7e

File tree

3 files changed

+136
-13
lines changed

3 files changed

+136
-13
lines changed

library/alloc/src/fmt.rs

+2
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,8 @@
555555
pub use core::fmt::Alignment;
556556
#[stable(feature = "rust1", since = "1.0.0")]
557557
pub use core::fmt::Error;
558+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
559+
pub use core::fmt::FormatterFn;
558560
#[stable(feature = "rust1", since = "1.0.0")]
559561
pub use core::fmt::{write, Arguments};
560562
#[stable(feature = "rust1", since = "1.0.0")]

library/core/src/fmt/builders.rs

+131-13
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
130130
/// ```
131131
#[stable(feature = "debug_builders", since = "1.2.0")]
132132
pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self {
133+
self.field_with(name, |f| value.fmt(f))
134+
}
135+
136+
/// Adds a new field to the generated struct output.
137+
///
138+
/// This method is equivalent to [`DebugStruct::field`], but formats the
139+
/// value using a provided closure rather than by calling [`Debug::fmt`].
140+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
141+
pub fn field_with<F>(&mut self, name: &str, value_fmt: F) -> &mut Self
142+
where
143+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
144+
{
133145
self.result = self.result.and_then(|_| {
134146
if self.is_pretty() {
135147
if !self.has_fields {
@@ -140,14 +152,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
140152
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
141153
writer.write_str(name)?;
142154
writer.write_str(": ")?;
143-
value.fmt(&mut writer)?;
155+
value_fmt(&mut writer)?;
144156
writer.write_str(",\n")
145157
} else {
146158
let prefix = if self.has_fields { ", " } else { " { " };
147159
self.fmt.write_str(prefix)?;
148160
self.fmt.write_str(name)?;
149161
self.fmt.write_str(": ")?;
150-
value.fmt(self.fmt)
162+
value_fmt(self.fmt)
151163
}
152164
});
153165

@@ -315,6 +327,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
315327
/// ```
316328
#[stable(feature = "debug_builders", since = "1.2.0")]
317329
pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
330+
self.field_with(|f| value.fmt(f))
331+
}
332+
333+
/// Adds a new field to the generated tuple struct output.
334+
///
335+
/// This method is equivalent to [`DebugTuple::field`], but formats the
336+
/// value using a provided closure rather than by calling [`Debug::fmt`].
337+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
338+
pub fn field_with<F>(&mut self, value_fmt: F) -> &mut Self
339+
where
340+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
341+
{
318342
self.result = self.result.and_then(|_| {
319343
if self.is_pretty() {
320344
if self.fields == 0 {
@@ -323,12 +347,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
323347
let mut slot = None;
324348
let mut state = Default::default();
325349
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
326-
value.fmt(&mut writer)?;
350+
value_fmt(&mut writer)?;
327351
writer.write_str(",\n")
328352
} else {
329353
let prefix = if self.fields == 0 { "(" } else { ", " };
330354
self.fmt.write_str(prefix)?;
331-
value.fmt(self.fmt)
355+
value_fmt(self.fmt)
332356
}
333357
});
334358

@@ -385,7 +409,10 @@ struct DebugInner<'a, 'b: 'a> {
385409
}
386410

387411
impl<'a, 'b: 'a> DebugInner<'a, 'b> {
388-
fn entry(&mut self, entry: &dyn fmt::Debug) {
412+
fn entry_with<F>(&mut self, entry_fmt: F)
413+
where
414+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
415+
{
389416
self.result = self.result.and_then(|_| {
390417
if self.is_pretty() {
391418
if !self.has_fields {
@@ -394,13 +421,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
394421
let mut slot = None;
395422
let mut state = Default::default();
396423
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
397-
entry.fmt(&mut writer)?;
424+
entry_fmt(&mut writer)?;
398425
writer.write_str(",\n")
399426
} else {
400427
if self.has_fields {
401428
self.fmt.write_str(", ")?
402429
}
403-
entry.fmt(self.fmt)
430+
entry_fmt(self.fmt)
404431
}
405432
});
406433

@@ -475,7 +502,20 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
475502
/// ```
476503
#[stable(feature = "debug_builders", since = "1.2.0")]
477504
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
478-
self.inner.entry(entry);
505+
self.inner.entry_with(|f| entry.fmt(f));
506+
self
507+
}
508+
509+
/// Adds a new entry to the set output.
510+
///
511+
/// This method is equivalent to [`DebugSet::entry`], but formats the
512+
/// entry using a provided closure rather than by calling [`Debug::fmt`].
513+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
514+
pub fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
515+
where
516+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
517+
{
518+
self.inner.entry_with(entry_fmt);
479519
self
480520
}
481521

@@ -605,7 +645,20 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
605645
/// ```
606646
#[stable(feature = "debug_builders", since = "1.2.0")]
607647
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
608-
self.inner.entry(entry);
648+
self.inner.entry_with(|f| entry.fmt(f));
649+
self
650+
}
651+
652+
/// Adds a new entry to the list output.
653+
///
654+
/// This method is equivalent to [`DebugList::entry`], but formats the
655+
/// entry using a provided closure rather than by calling [`Debug::fmt`].
656+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
657+
pub fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
658+
where
659+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
660+
{
661+
self.inner.entry_with(entry_fmt);
609662
self
610663
}
611664

@@ -775,6 +828,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
775828
/// ```
776829
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
777830
pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self {
831+
self.key_with(|f| key.fmt(f))
832+
}
833+
834+
/// Adds the key part of a new entry to the map output.
835+
///
836+
/// This method is equivalent to [`DebugMap::key`], but formats the
837+
/// key using a provided closure rather than by calling [`Debug::fmt`].
838+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
839+
pub fn key_with<F>(&mut self, key_fmt: F) -> &mut Self
840+
where
841+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
842+
{
778843
self.result = self.result.and_then(|_| {
779844
assert!(
780845
!self.has_key,
@@ -789,13 +854,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
789854
let mut slot = None;
790855
self.state = Default::default();
791856
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
792-
key.fmt(&mut writer)?;
857+
key_fmt(&mut writer)?;
793858
writer.write_str(": ")?;
794859
} else {
795860
if self.has_fields {
796861
self.fmt.write_str(", ")?
797862
}
798-
key.fmt(self.fmt)?;
863+
key_fmt(self.fmt)?;
799864
self.fmt.write_str(": ")?;
800865
}
801866

@@ -839,16 +904,28 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
839904
/// ```
840905
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
841906
pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self {
907+
self.value_with(|f| value.fmt(f))
908+
}
909+
910+
/// Adds the value part of a new entry to the map output.
911+
///
912+
/// This method is equivalent to [`DebugMap::value`], but formats the
913+
/// value using a provided closure rather than by calling [`Debug::fmt`].
914+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
915+
pub fn value_with<F>(&mut self, value_fmt: F) -> &mut Self
916+
where
917+
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
918+
{
842919
self.result = self.result.and_then(|_| {
843920
assert!(self.has_key, "attempted to format a map value before its key");
844921

845922
if self.is_pretty() {
846923
let mut slot = None;
847924
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
848-
value.fmt(&mut writer)?;
925+
value_fmt(&mut writer)?;
849926
writer.write_str(",\n")?;
850927
} else {
851-
value.fmt(self.fmt)?;
928+
value_fmt(self.fmt)?;
852929
}
853930

854931
self.has_key = false;
@@ -936,3 +1013,44 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
9361013
self.fmt.alternate()
9371014
}
9381015
}
1016+
1017+
/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
1018+
///
1019+
/// # Examples
1020+
///
1021+
/// ```
1022+
/// #![feature(debug_closure_helpers)]
1023+
/// use std::fmt;
1024+
///
1025+
/// let value = 'a';
1026+
/// assert_eq!(format!("{}", value), "a");
1027+
/// assert_eq!(format!("{:?}", value), "'a'");
1028+
///
1029+
/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value));
1030+
/// assert_eq!(format!("{}", wrapped), "'a'");
1031+
/// assert_eq!(format!("{:?}", wrapped), "'a'");
1032+
/// ```
1033+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
1034+
pub struct FormatterFn<F>(pub F)
1035+
where
1036+
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
1037+
1038+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
1039+
impl<F> fmt::Debug for FormatterFn<F>
1040+
where
1041+
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
1042+
{
1043+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1044+
(self.0)(f)
1045+
}
1046+
}
1047+
1048+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
1049+
impl<F> fmt::Display for FormatterFn<F>
1050+
where
1051+
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
1052+
{
1053+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1054+
(self.0)(f)
1055+
}
1056+
}

library/core/src/fmt/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ pub enum Alignment {
3939
#[stable(feature = "debug_builders", since = "1.2.0")]
4040
pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
4141

42+
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
43+
pub use self::builders::FormatterFn;
44+
4245
/// The type returned by formatter methods.
4346
///
4447
/// # Examples

0 commit comments

Comments
 (0)