Crate displaydoc

source ·
Expand description

This library provides a convenient derive macro for the standard library’s core::fmt::Display trait.

[dependencies]
displaydoc = "0.2"

Compiler support: requires rustc 1.56+


Example

Demonstration alongside the Error derive macro from thiserror, to propagate source locations from io::Error with the #[source] attribute:

use std::io;
use displaydoc::Display;
use thiserror::Error;

#[derive(Display, Error, Debug)]
pub enum DataStoreError {
    /// data store disconnected
    Disconnect(#[source] io::Error),
    /// the data for key `{0}` is not available
    Redaction(String),
    /// invalid header (expected {expected:?}, found {found:?})
    InvalidHeader {
        expected: String,
        found: String,
    },
    /// unknown data store error
    Unknown,
}

let error = DataStoreError::Redaction("CLASSIFIED CONTENT".to_string());
assert!("the data for key `CLASSIFIED CONTENT` is not available" == &format!("{}", error));

Note that although io::Error implements Display, we do not add it to the generated message for DataStoreError::Disconnect, since it is already made available via #[source]. See further context on avoiding duplication in error reports at the rust blog here.


Details

  • A fmt::Display impl is generated for your enum if you provide a docstring comment on each variant as shown above in the example. The Display derive macro supports a shorthand for interpolating fields from the error:
    • /// {var}write!("{}", self.var)
    • /// {0}write!("{}", self.0)
    • /// {var:?}write!("{:?}", self.var)
    • /// {0:?}write!("{:?}", self.0)
  • This also works with structs and generic types:
/// oh no, an error: {0}
#[derive(Display)]
pub struct Error<E>(pub E);

let error: Error<&str> = Error("muahaha i am an error");
assert!("oh no, an error: muahaha i am an error" == &format!("{}", error));
  • Two optional attributes can be added to your types next to the derive:

    • #[ignore_extra_doc_attributes] makes the macro ignore any doc comment attributes (or /// lines) after the first. Multi-line comments using /// are otherwise treated as an error, so use this attribute or consider switching to block doc comments (/** */).

    • #[prefix_enum_doc_attributes] combines the doc comment message on your enum itself with the messages for each variant, in the format “enum: variant”. When added to an enum, the doc comment on the enum becomes mandatory. When added to any other type, it has no effect.

  • In case you want to have an independent doc comment, the #[displaydoc("...") atrribute may be used on the variant or struct to override it.


FAQ

  1. Is this crate no_std compatible?

    • Yes! This crate implements the core::fmt::Display trait, not the std::fmt::Display trait, so it should work in std and no_std environments. Just add default-features = false.
  2. Does this crate work with Path and PathBuf via the Display trait?

    • Yuuup. This crate uses @dtolnay’s autoref specialization technique to add a special trait for types to get the display impl. It then specializes for Path and PathBuf, and when either of these types are found, it calls self.display() to get a std::path::Display<'_> type which can be used with the Display format specifier!

Derive Macros