From 198c1abc4eca2a95f5b36a1af25cfd6b28d4b85f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 04:34:27 +0100 Subject: [PATCH 1/7] add core/alloc/std::fmt::WrapDebug --- src/liballoc/fmt.rs | 3 +++ src/liballoc/lib.rs | 1 + src/libcore/fmt/mod.rs | 60 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index a092bfb3b0a8a..5ce52182e38af 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -528,6 +528,9 @@ pub use core::fmt::{ArgumentV1, Arguments, write}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[unstable(feature = "wrap_debug", issue = "0")] +pub use core::fmt::WrapDebug; + use string; /// The `format` function takes an [`Arguments`] struct and returns the resulting diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b93e128d50819..0503df9a3290e 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -125,6 +125,7 @@ #![feature(on_unimplemented)] #![feature(exact_chunks)] #![feature(pointer_methods)] +#![feature(wrap_debug)] #![cfg_attr(not(test), feature(fn_traits, placement_new_protocol, swap_with_slice, i128))] #![cfg_attr(test, feature(test, box_heap))] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 67126b496e211..d053695eee416 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1960,5 +1960,65 @@ impl Debug for UnsafeCell { } } +/// A wrapper around a type `T` where `T: Debug` possibly holds. If it does, +/// then the `Debug` impl of `T` will be used in `impl Debug for WrapDebug`. +/// Otherwise (if `T: !Debug`), `impl Debug for WrapDebug` will output with +/// the type name of `T` and that `T` is `!Debug`. +/// +/// `WrapDebug` is useful to avoid `Debug` bounds when trying to debug things +/// in generic code. Without `WrapDebug`, your generic call stack will get +/// infected with `T: Debug` bounds until the type is known. +/// +/// This type is particularly useful for macro authors. +/// +/// # Guarantees +/// +/// `WrapDebug` makes the guarantee that `impl Debug for WrapDebug` +/// exists. At the same time, `WrapDebug` makes **no** guarantee (yet) that +/// `impl Debug for WrapDebug` exists. Neither should you rely +/// on the stability of `WrapDebug`'s output format. +/// +/// # Examples +/// +/// `WrapDebug` where `T: Debug` will use the `Debug` implementation of `T`: +/// +/// ```rust +/// #![feature(wrap_debug)] +/// use std::fmt::WrapDebug; +/// +/// assert_eq!(format!("{:?}", WrapDebug(0)), "0"); +/// ``` +/// +/// `WrapDebug` where `T: !Debug` is `Debug` and outputs the type name: +/// +/// ```rust +/// #![feature(wrap_debug)] +/// use std::fmt::WrapDebug; +/// +/// struct NotDebug; +/// assert_eq!(format!("{:?}", WrapDebug(NotDebug)), +/// "[ of type main::NotDebug is !Debug]"); +/// ``` +#[unstable(feature = "wrap_debug", issue = "0")] +#[derive(Copy, Clone)] +pub struct WrapDebug(pub T); + +#[unstable(feature = "wrap_debug", issue = "0")] +impl Debug for WrapDebug { + // FIXME: remove this impl if specialization doesn't pan out! + + fn fmt(&self, fmt: &mut Formatter) -> Result { + self.0.fmt(fmt) + } +} + +#[unstable(feature = "wrap_debug", issue = "0")] +impl Debug for WrapDebug { + default fn fmt(&self, fmt: &mut Formatter) -> Result { + write!(fmt, "[ of type {} is !Debug]", + unsafe { intrinsics::type_name::() }) + } +} + // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, // it's a lot easier than creating all of the rt::Piece structures here. From 3c314fad710c10d6f5462b7245a2485565cb466d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 04:39:18 +0100 Subject: [PATCH 2/7] add core/alloc/std::fmt::WrapDebug - #![feature(core_intrinsics)] in libcore --- src/libcore/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a947c9f0b7c13..73951f9a66c07 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -101,6 +101,7 @@ #![feature(unboxed_closures)] #![feature(untagged_unions)] #![feature(unwind_attributes)] +#![feature(core_intrinsics)] #![cfg_attr(stage0, allow(unused_attributes))] #![cfg_attr(stage0, feature(never_type))] From 05287c8bbcf6905b8ea7d25cf6db43f46736dae6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 04:40:44 +0100 Subject: [PATCH 3/7] add core/alloc/std::fmt::WrapDebug - global path core::intrinsics::type_name --- src/libcore/fmt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index d053695eee416..19138c6902e89 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -2016,7 +2016,7 @@ impl Debug for WrapDebug { impl Debug for WrapDebug { default fn fmt(&self, fmt: &mut Formatter) -> Result { write!(fmt, "[ of type {} is !Debug]", - unsafe { intrinsics::type_name::() }) + unsafe { ::core::intrinsics::type_name::() }) } } From d61e0b6576f42dd90e12e41c677a49ed874b5aec Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 04:48:33 +0100 Subject: [PATCH 4/7] add core/alloc/std::fmt::WrapDebug - fix use intrinsics::type_name --- src/libcore/fmt/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 19138c6902e89..404d5ef3187ee 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -2015,8 +2015,10 @@ impl Debug for WrapDebug { #[unstable(feature = "wrap_debug", issue = "0")] impl Debug for WrapDebug { default fn fmt(&self, fmt: &mut Formatter) -> Result { + use intrinsics::type_name; + write!(fmt, "[ of type {} is !Debug]", - unsafe { ::core::intrinsics::type_name::() }) + unsafe { type_name::() }) } } From b472dc2ce0e7604e78e6fb3c4417b22d89e4d5c0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 05:17:55 +0100 Subject: [PATCH 5/7] add core/alloc/std::fmt::WrapDebug - rewrite logic using `trait WrapDebugInternal` --- src/libcore/fmt/mod.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 404d5ef3187ee..3adcce4ba63ca 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1974,9 +1974,10 @@ impl Debug for UnsafeCell { /// # Guarantees /// /// `WrapDebug` makes the guarantee that `impl Debug for WrapDebug` -/// exists. At the same time, `WrapDebug` makes **no** guarantee (yet) that -/// `impl Debug for WrapDebug` exists. Neither should you rely -/// on the stability of `WrapDebug`'s output format. +/// exists. However, you should not rely on the stability of `WrapDebug`'s +/// output format. In particular, no guarantee is made that the `type_name` +/// is included when `T: !Debug` or that `::fmt` is used when +/// `T: Debug`. /// /// # Examples /// @@ -2004,21 +2005,26 @@ impl Debug for UnsafeCell { pub struct WrapDebug(pub T); #[unstable(feature = "wrap_debug", issue = "0")] -impl Debug for WrapDebug { - // FIXME: remove this impl if specialization doesn't pan out! - +impl Debug for WrapDebug { fn fmt(&self, fmt: &mut Formatter) -> Result { - self.0.fmt(fmt) + ::fmt(self, fmt) } } -#[unstable(feature = "wrap_debug", issue = "0")] -impl Debug for WrapDebug { - default fn fmt(&self, fmt: &mut Formatter) -> Result { - use intrinsics::type_name; +trait WrapDebugInternal { + fn fmt(&self, fmt: &mut Formatter) -> Result; +} +impl WrapDebugInternal for WrapDebug { + default fn fmt(&self, fmt: &mut Formatter) -> Result { write!(fmt, "[ of type {} is !Debug]", - unsafe { type_name::() }) + unsafe { intrinsics::type_name::() }) + } +} + +impl WrapDebugInternal for WrapDebug { + fn fmt(&self, fmt: &mut Formatter) -> Result { + self.0.fmt(fmt) } } From f36dc46adffe1b645e23f9607d0dfc6692146149 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 05:18:58 +0100 Subject: [PATCH 6/7] add core/alloc/std::fmt::WrapDebug - fix use intrinsics::type_name --- src/libcore/fmt/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 3adcce4ba63ca..5f32c4c3ff80a 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -2017,8 +2017,9 @@ trait WrapDebugInternal { impl WrapDebugInternal for WrapDebug { default fn fmt(&self, fmt: &mut Formatter) -> Result { + use intrinsics::type_name; write!(fmt, "[ of type {} is !Debug]", - unsafe { intrinsics::type_name::() }) + unsafe { type_name::() }) } } From 88a196b6a4b692135745ec73687c8bf9c6e3958d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 16 Mar 2018 08:13:26 +0100 Subject: [PATCH 7/7] rename WrapDebug to BestEffortDebug --- src/liballoc/fmt.rs | 4 ++-- src/liballoc/lib.rs | 2 +- src/libcore/fmt/mod.rs | 51 ++++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 5ce52182e38af..d324167d6edda 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -528,8 +528,8 @@ pub use core::fmt::{ArgumentV1, Arguments, write}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; -#[unstable(feature = "wrap_debug", issue = "0")] -pub use core::fmt::WrapDebug; +#[unstable(feature = "best_effort_debug", issue = "0")] +pub use core::fmt::BestEffortDebug; use string; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 7194419413d1a..8c722cef33066 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -124,8 +124,8 @@ #![feature(on_unimplemented)] #![feature(exact_chunks)] #![feature(pointer_methods)] -#![feature(wrap_debug)] #![feature(inclusive_range_fields)] +#![feature(best_effort_debug)] #![cfg_attr(not(test), feature(fn_traits, placement_new_protocol, swap_with_slice, i128))] #![cfg_attr(test, feature(test, box_heap))] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 5f32c4c3ff80a..f2eed892f6341 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1961,61 +1961,64 @@ impl Debug for UnsafeCell { } /// A wrapper around a type `T` where `T: Debug` possibly holds. If it does, -/// then the `Debug` impl of `T` will be used in `impl Debug for WrapDebug`. -/// Otherwise (if `T: !Debug`), `impl Debug for WrapDebug` will output with -/// the type name of `T` and that `T` is `!Debug`. +/// then the `Debug` impl of `T` will be used in +/// `impl Debug for BestEffortDebug`. +/// Otherwise (if `T: !Debug`), `impl Debug for BestEffortDebug` +/// will output with the type name of `T` and that `T` is `!Debug`. /// -/// `WrapDebug` is useful to avoid `Debug` bounds when trying to debug things -/// in generic code. Without `WrapDebug`, your generic call stack will get -/// infected with `T: Debug` bounds until the type is known. +/// `BestEffortDebug` is useful to avoid `Debug` bounds when trying to debug +/// things in generic code. Without `BestEffortDebug`, your generic call stack +/// will get infected with `T: Debug` bounds until the type is known. /// /// This type is particularly useful for macro authors. /// /// # Guarantees /// -/// `WrapDebug` makes the guarantee that `impl Debug for WrapDebug` -/// exists. However, you should not rely on the stability of `WrapDebug`'s +/// `BestEffortDebug` makes the guarantee that +/// `impl Debug for BestEffortDebug` exists. +/// However, you should not rely on the stability of `BestEffortDebug`'s /// output format. In particular, no guarantee is made that the `type_name` /// is included when `T: !Debug` or that `::fmt` is used when /// `T: Debug`. /// /// # Examples /// -/// `WrapDebug` where `T: Debug` will use the `Debug` implementation of `T`: +/// `BestEffortDebug` where `T: Debug` will use the `Debug` +/// implementation of `T`: /// /// ```rust -/// #![feature(wrap_debug)] -/// use std::fmt::WrapDebug; +/// #![feature(best_effort_debug)] +/// use std::fmt::BestEffortDebug; /// -/// assert_eq!(format!("{:?}", WrapDebug(0)), "0"); +/// assert_eq!(format!("{:?}", BestEffortDebug(0)), "0"); /// ``` /// -/// `WrapDebug` where `T: !Debug` is `Debug` and outputs the type name: +/// `BestEffortDebug` where `T: !Debug` is `Debug` and outputs the type name: /// /// ```rust -/// #![feature(wrap_debug)] -/// use std::fmt::WrapDebug; +/// #![feature(best_effort_debug)] +/// use std::fmt::BestEffortDebug; /// /// struct NotDebug; -/// assert_eq!(format!("{:?}", WrapDebug(NotDebug)), +/// assert_eq!(format!("{:?}", BestEffortDebug(NotDebug)), /// "[ of type main::NotDebug is !Debug]"); /// ``` -#[unstable(feature = "wrap_debug", issue = "0")] +#[unstable(feature = "best_effort_debug", issue = "0")] #[derive(Copy, Clone)] -pub struct WrapDebug(pub T); +pub struct BestEffortDebug(pub T); -#[unstable(feature = "wrap_debug", issue = "0")] -impl Debug for WrapDebug { +#[unstable(feature = "best_effort_debug", issue = "0")] +impl Debug for BestEffortDebug { fn fmt(&self, fmt: &mut Formatter) -> Result { - ::fmt(self, fmt) + ::fmt(self, fmt) } } -trait WrapDebugInternal { +trait BEDInternal { fn fmt(&self, fmt: &mut Formatter) -> Result; } -impl WrapDebugInternal for WrapDebug { +impl BEDInternal for BestEffortDebug { default fn fmt(&self, fmt: &mut Formatter) -> Result { use intrinsics::type_name; write!(fmt, "[ of type {} is !Debug]", @@ -2023,7 +2026,7 @@ impl WrapDebugInternal for WrapDebug { } } -impl WrapDebugInternal for WrapDebug { +impl BEDInternal for BestEffortDebug { fn fmt(&self, fmt: &mut Formatter) -> Result { self.0.fmt(fmt) }