Replace stringify! in Debug impls with type checked macro

Add identify! macro which expands to stringify! but also const type
checks the value to prevent typos/wrong values.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/425/head
Manos Pitsidianakis 4 months ago
parent e107d613a0
commit 6da4e2eca6
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -36,8 +36,8 @@ pub enum HookFn {
}
impl std::fmt::Debug for HookFn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct(stringify!(HookFn))
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(melib::identify!(HookFn))
.field(
"kind",
&match self {

@ -108,7 +108,7 @@ pub struct ViewFilter {
impl std::fmt::Debug for ViewFilter {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(stringify!(ViewFilter))
fmt.debug_struct(melib::identify!(ViewFilter))
.field("filter_invocation", &self.filter_invocation)
.field("content_type", &self.content_type)
.field("notice", &self.notice)

@ -37,7 +37,7 @@ pub struct HtmlView {
impl std::fmt::Debug for HtmlView {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(stringify!(HtmlView))
fmt.debug_struct(melib::identify!(HtmlView))
.field("pager", &self.pager)
.field("bytes", &self.bytes.len())
.field("coordinates", &self.coordinates)

@ -233,7 +233,7 @@ impl Component for NotificationCommand {
Ok(child) => {
context
.children
.entry(stringify!(NotificationCommand).into())
.entry(melib::identify!(NotificationCommand).into())
.or_default()
.push(child);
}
@ -268,7 +268,7 @@ impl Component for NotificationCommand {
Ok(child) => {
context
.children
.entry(stringify!(NotificationCommand).into())
.entry(melib::identify!(NotificationCommand).into())
.or_default()
.push(child);
return false;

@ -79,8 +79,8 @@ pub struct CellBuffer {
}
impl std::fmt::Debug for CellBuffer {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct(stringify!(CellBuffer))
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(melib::identify!(CellBuffer))
.field("cols", &self.cols)
.field("rows", &self.rows)
.field("buf cells", &self.buf.len())
@ -1425,7 +1425,7 @@ pub struct BoundsIterator {
impl std::fmt::Debug for BoundsIterator {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct(stringify!(BoundsIterator))
f.debug_struct(melib::identify!(BoundsIterator))
.field("rows", &self.rows)
.field("cols", &self.cols)
.field("width", &self.width)

@ -188,7 +188,7 @@ pub struct CallbackFn(pub Box<dyn FnOnce(&mut crate::Context) + Send + 'static>)
impl std::fmt::Debug for CallbackFn {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "CallbackFn")
fmt.debug_struct(melib::identify!(CallbackFn)).finish()
}
}

@ -30,7 +30,7 @@ pub struct TextField {
impl std::fmt::Debug for TextField {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(stringify!(TextField))
fmt.debug_struct(melib::identify!(TextField))
.field("id", &self.id)
.field("inner", &self.inner)
.field("has AutoComplete", &self.autocomplete.is_some())

@ -324,8 +324,9 @@ impl BackendEventConsumer {
}
impl std::fmt::Debug for BackendEventConsumer {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, stringify!(BackendEventConsumer))
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(crate::identify!(BackendEventConsumer))
.finish()
}
}
@ -714,7 +715,7 @@ pub struct LazyCountSet {
impl std::fmt::Debug for LazyCountSet {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("LazyCountSet")
f.debug_struct(crate::identify!(LazyCountSet))
.field("not_yet_seen", &self.not_yet_seen)
.field("set", &self.set.len())
.field("total_len", &self.len())
@ -786,7 +787,7 @@ pub struct IsSubscribedFn(pub Box<dyn Fn(&str) -> bool + Send + Sync>);
impl std::fmt::Debug for IsSubscribedFn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "IsSubscribedFn Box")
f.debug_struct(crate::identify!(IsSubscribedFn)).finish()
}
}

@ -293,7 +293,7 @@ pub struct Envelope {
impl std::fmt::Debug for Envelope {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Envelope")
f.debug_struct(crate::identify!(Envelope))
.field("Subject", &self.subject())
.field("Date", &self.date)
.field("From", &self.from)

@ -444,7 +444,7 @@ impl std::fmt::Debug for Address {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Mailbox(m) => f
.debug_struct("Address::Mailbox")
.debug_struct(stringify!(Address::Mailbox))
.field("display_name", &m.display_name.display(&m.raw))
.field("address_spec", &m.address_spec.display(&m.raw))
.finish(),
@ -452,7 +452,7 @@ impl std::fmt::Debug for Address {
let attachment_strings: Vec<String> =
g.mailbox_list.iter().map(|a| format!("{}", a)).collect();
f.debug_struct("Address::Group")
f.debug_struct(stringify!(Address::Group))
.field("display_name", &g.display_name.display(&g.raw))
.field("addresses", &attachment_strings.join(", "))
.finish()

@ -408,7 +408,7 @@ impl std::fmt::Debug for Attachment {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut text = Vec::with_capacity(4096);
self.get_text_recursive(&Text::Plain, &mut text);
f.debug_struct("Attachment")
f.debug_struct(crate::identify!(Attachment))
.field("Content-Type", &self.content_type)
.field("Content-Transfer-Encoding", &self.content_transfer_encoding)
.field("bytes", &self.raw.len())

@ -94,7 +94,7 @@ impl std::fmt::Debug for InvalidHeaderName {
impl std::fmt::Display for InvalidHeaderName {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, "{}", stringify!(InvalidHeaderName))
write!(fmt, "{}", crate::identify!(InvalidHeaderName))
}
}

@ -73,7 +73,7 @@ impl std::fmt::Debug for ParsingError<&'_ [u8]> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
#[cfg(any(test, doc))]
{
fmt.debug_struct("ParsingError")
fmt.debug_struct(stringify!(ParsingError))
.field("input", &to_str!(self.input))
.field("error", &self.error)
.field("backtrace", &self.backtrace)
@ -81,7 +81,7 @@ impl std::fmt::Debug for ParsingError<&'_ [u8]> {
}
#[cfg(not(any(test, doc)))]
{
fmt.debug_struct("ParsingError")
fmt.debug_struct(stringify!(ParsingError))
.field("input", &to_str!(self.input))
.field("error", &self.error)
.finish()
@ -93,7 +93,7 @@ impl std::fmt::Debug for ParsingError<&'_ str> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
#[cfg(any(test, doc))]
{
fmt.debug_struct("ParsingError")
fmt.debug_struct(stringify!(ParsingError))
.field("input", &self.input)
.field("error", &self.error)
.field("backtrace", &self.backtrace)
@ -101,7 +101,7 @@ impl std::fmt::Debug for ParsingError<&'_ str> {
}
#[cfg(not(any(test, doc)))]
{
fmt.debug_struct("ParsingError")
fmt.debug_struct(stringify!(ParsingError))
.field("input", &self.input)
.field("error", &self.error)
.finish()

@ -1312,7 +1312,7 @@ impl Key {
impl std::fmt::Debug for Key {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct("Key")
fmt.debug_struct(crate::identify!(Key))
.field("fingerprint", &self.fingerprint())
.field("uid", &self.primary_uid())
.field("can_encrypt", &self.can_encrypt())

@ -51,7 +51,7 @@ pub struct Session {
}
impl Object for Session {
const NAME: &'static str = stringify!(Session);
const NAME: &'static str = crate::identify!(Session);
}
impl Session {

@ -276,7 +276,7 @@ impl Serialize for EmailSubmissionObject {
where
S: Serializer,
{
let mut state = serializer.serialize_struct(stringify! {EmailSubmissionObject}, 4)?;
let mut state = serializer.serialize_struct(crate::identify!(EmailSubmissionObject), 4)?;
state.serialize_field("identityId", &self.identity_id)?;
state.serialize_field(
if matches!(self.email_id, Argument::Value(_)) {

@ -74,7 +74,7 @@ impl std::fmt::Debug for Connection {
ref inner,
ref id,
} => fmt
.debug_struct(stringify!(Connection))
.debug_struct(crate::identify!(Connection))
.field("variant", &stringify!(Tcp))
.field(stringify!(trace), trace)
.field(stringify!(id), id)
@ -86,7 +86,7 @@ impl std::fmt::Debug for Connection {
ref inner,
ref id,
} => fmt
.debug_struct(stringify!(Connection))
.debug_struct(crate::identify!(Connection))
.field("variant", &stringify!(Tls))
.field(stringify!(trace), trace)
.field(stringify!(id), id)
@ -97,7 +97,7 @@ impl std::fmt::Debug for Connection {
ref inner,
ref id,
} => fmt
.debug_struct(stringify!(Connection))
.debug_struct(crate::identify!(Connection))
.field("variant", &stringify!(Fd))
.field(stringify!(trace), trace)
.field(stringify!(id), id)
@ -108,7 +108,7 @@ impl std::fmt::Debug for Connection {
ref inner,
ref id,
} => fmt
.debug_struct(stringify!(Connection))
.debug_struct(crate::identify!(Connection))
.field("variant", &stringify!(Deflate))
.field(stringify!(trace), trace)
.field(stringify!(id), id)

@ -153,7 +153,7 @@ pub struct StderrLogger {
impl std::fmt::Debug for StderrLogger {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(stringify!(StderrLogger))
fmt.debug_struct(crate::identify!(StderrLogger))
.field("level", &LogLevel::from(self.level.load(Ordering::SeqCst)))
.field("print_level", &self.print_level)
.field("print_module_names", &self.print_module_names)

@ -238,3 +238,58 @@ pub mod hostname {
retval
}
}
#[macro_export]
/// For use with `debug_struct` in `Debug` implementations to prevent stale type
/// names after renaming or typos during compilation.
///
/// # Example
///
/// ```no_run
/// # use melib::identify;
/// struct Envelope;
///
/// impl std::fmt::Debug for Envelope {
/// fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
/// f.debug_struct(identify!(Envelope))
/// .field("Subject", &"foobar")
/// .finish()
/// }
/// }
/// ```
///
/// Using it with an invalid identifier will fail:
///
/// ```no_run,compile_fail
/// # use melib::identify;
/// struct Envelope;
///
/// impl std::fmt::Debug for Envelope {
/// fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
/// f.debug_struct(identify!(Enzelope))
/// .field("Subject", &"foobar")
/// .finish()
/// }
/// }
/// ```
///
/// This will fail with:
///
/// ```text
/// error[E0412]: cannot find type `Enzelope` in this scope
/// |
/// ___ | struct Envelope;
/// | ------------------- similarly named struct `Envelope` defined here
/// ...
/// ___ | f.debug_struct(identify!(Enzelope))
/// | ^^^^^^^^ help: a struct with a similar name exists: `Envelope`
/// ```
macro_rules! identify {
($f:tt$($t:tt)*) => {{
const fn __debugify() -> ::core::marker::PhantomData<$f$($t)*> {
core::marker::PhantomData
}
let _: ::core::marker::PhantomData<Self> = __debugify();
stringify!($f$($t)*)
}};
}

Loading…
Cancel
Save