Skip to content

Commit c09b799

Browse files
committed
core: give SetGlobalDefaultError a useful Debug impl (#2250)
## Motivation When a global default dispatcher has already been set, the `dispatch::set_global_default` function fails with a `SetGlobalDefaultError`. The `fmt::Display` impl for this type includes a message explaining that the error indicates that a global default has already been set, but the `fmt::Debug` impl is derived, and just looks like this: ``` SetGlobalDefaultError { _no_construct: () } ``` which isn't particularly helpful. Unfortunately, when `unwrap()`ping or `expect()`ing a `Result`, the `fmt::Debug` implementation for the error type is used, rather than `fmt::Display`. This means that the error message will not explain to the user why setting the global default dispatcher failed, which is a bummer. ## Solution This branch replaces the derived `Debug` impl with a manually implemented one that prints the same message as the `Display` impl, but formatted like a tuple struct with a single string field. This avoids emitting `Debug` output that's *just* a textual human-readable message, rather than looking like Rust code, but ensures the message is visible to the user when writing code like ```rust tracing::dispatch::set_global_default(foo).unwrap(); ``` The mesasge now looks like: ``` SetGlobalDefaultError("a global default trace dispatcher has already been set") ``` which should be a bit easier to debug.
1 parent c1a27bf commit c09b799

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

tracing-core/src/dispatcher.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,21 +293,32 @@ pub fn has_been_set() -> bool {
293293
}
294294

295295
/// Returned if setting the global dispatcher fails.
296-
#[derive(Debug)]
297296
pub struct SetGlobalDefaultError {
298297
_no_construct: (),
299298
}
300299

300+
impl fmt::Debug for SetGlobalDefaultError {
301+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302+
f.debug_tuple("SetGlobalDefaultError")
303+
.field(&Self::MESSAGE)
304+
.finish()
305+
}
306+
}
307+
301308
impl fmt::Display for SetGlobalDefaultError {
302309
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303-
f.pad("a global default trace dispatcher has already been set")
310+
f.pad(Self::MESSAGE)
304311
}
305312
}
306313

307314
#[cfg(feature = "std")]
308315
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
309316
impl error::Error for SetGlobalDefaultError {}
310317

318+
impl SetGlobalDefaultError {
319+
const MESSAGE: &'static str = "a global default trace dispatcher has already been set";
320+
}
321+
311322
/// Executes a closure with a reference to this thread's current [dispatcher].
312323
///
313324
/// Note that calls to `get_default` should not be nested; if this function is

0 commit comments

Comments
 (0)