Skip to content

Feature Request: downcasting Log, but for real #666

@1e1001

Description

@1e1001

Seems #399 was already closed (4.5 years ago, for bad usecase & maybe backwards compatibility reasons?), but I have an actual use!

My logger writes a message on panic, but does so with a custom format different to anything you can write with the Log trait. So I need to be able to downcast the &dyn Log into my own logger from the panic handler. I could probably use a OnceLock to store if my logger's been initialized but log already does that with the (set_)logger methods, so it feels redundant.

For now my current way of doing this is this very cursed set of functions:

fn as_dyn_ref(logger: *const Logger) -> *const dyn Log {
  // split into one function to always attach the same metadata
  logger as *const dyn Log
}
fn upcast_log(logger: &'static Logger) -> &'static dyn Log {
  // SAFETY: as_dyn_ref returns a reference to the same object as passed in
  unsafe { &*as_dyn_ref(logger) }
}
fn downcast_log(log: &'static dyn Log) -> Option<&'static Logger> {
  // horribly cursed implementation to fetch a reference to the installed logger
  let (logger_ptr, logger_meta) = (&raw const *log).to_raw_parts();
  let (_, fake_logger_meta) = as_dyn_ref(ptr::null::<Logger>()).to_raw_parts();
  (logger_meta == fake_logger_meta).then(|| {
    // SAFETY: v-tables match so it's probably ours!
    unsafe { &*logger_ptr.cast::<Logger>() }
  })
}

but that's a lot of unsafe, and nightly-only.

To prevent needing to add a + 'static bound on Log (which probably breaks compatibility somehow), yandros suggested (in rplcs #dark-arts) adding something like:

fn type_id(&self) -> TypeId
  where Self: 'static
{
  TypeId::of<Self>()
}

as an automatic implementation on the Log trait.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions