Skip to content

Commit f6602ee

Browse files
authored
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 3a4d7be commit f6602ee

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

tracing-core/src/dispatch.rs

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

351351
/// Returned if setting the global dispatcher fails.
352-
#[derive(Debug)]
353352
pub struct SetGlobalDefaultError {
354353
_no_construct: (),
355354
}
356355

356+
impl fmt::Debug for SetGlobalDefaultError {
357+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358+
f.debug_tuple("SetGlobalDefaultError")
359+
.field(&Self::MESSAGE)
360+
.finish()
361+
}
362+
}
363+
357364
impl fmt::Display for SetGlobalDefaultError {
358365
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359-
f.pad("a global default trace dispatcher has already been set")
366+
f.pad(Self::MESSAGE)
360367
}
361368
}
362369

363370
#[cfg(feature = "std")]
364371
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
365372
impl error::Error for SetGlobalDefaultError {}
366373

374+
impl SetGlobalDefaultError {
375+
const MESSAGE: &'static str = "a global default trace dispatcher has already been set";
376+
}
377+
367378
/// Executes a closure with a reference to this thread's current [dispatcher].
368379
///
369380
/// Note that calls to `get_default` should not be nested; if this function is

0 commit comments

Comments
 (0)