Subject
displaydoc is a Rust procedural-macro crate by Jane Lusby (jlusby@yaah.dev) that provides a #[derive(Display)] macro. The derive synthesises a core::fmt::Display implementation for the annotated type from the /// doc comments on its variants (for enums) or on the type itself (for structs), with shorthand interpolation: {var} and {0} are rewritten to write!-style positional arguments. The crate ships one library target with proc-macro = true (src/lib.rs) and depends only on syn, quote, and proc-macro2. The std default feature enables a dtolnay-style autoref-specialization shim that lets {path} work with std::path::Path and std::path::PathBuf by calling self.display(); under --no-default-features the crate compiles for no_std consumers.
Methodology
Tooling used:
openvet audit new (0.x) to fetch and unpack the crate from crates.io and clone the GitHub repository at the commit recorded in .cargo_vcs_info.json.
diff -r (Apple Darwin) to compare published crate contents against the upstream VCS checkout.
grep / ripgrep-style searches across contents/src and contents/tests for unsafe, extern "C", std::process::, std::net::, std::fs::, env::, panic-prone calls (panic!, expect, unwrap, unimplemented!, unreachable!), and HTTP-client crates.
- Manual line-by-line read of all four files under
src/ (~900 lines total) and all five integration test files under tests/.
cargo build (1.x stable) on a small reproducer crate (tmp/repro/) to confirm one finding.
The published displaydoc-0.2.6.crate was diffed against the upstream repository at commit 50d6f1f (the commit pinned in .cargo_vcs_info.json). Source files (src/**/*.rs, tests/**/*.rs) match byte-for-byte; differences are limited to cargo's Cargo.toml normalisation and to files excluded by the include list (.github/, examples/, update-readme.sh, tests/ui/*.stderr, README.tpl).
The crate's runtime surface is the proc macro itself, which runs at compile time on every downstream consumer of #[derive(Display)]. The macro was inspected end to end: token-stream construction in src/expand.rs, the format-shorthand parser in src/fmt.rs, and the attribute extraction in src/attr.rs. The unit tests in src/fmt.rs::tests cover the format-shorthand expansion for both std and no_std configurations; the integration tests cover happy-path enum/struct expansion, no_std compilation, and a trybuild UI suite gated to nightly.
Results
The diff between published contents and VCS shows no unexpected changes. The crate contains no binary artefacts (justifying has-binaries) and no build.rs; the only build-time code is the proc-macro entry point itself (pub fn derive_error in src/lib.rs), which produces tokens by walking a syn::DeriveInput and emits no std::process, std::net, std::fs, or std::env calls — justifying build-exec-safe, build-exec-no-network, build-exec-no-write-out, build-exec-deterministic, and build-exec-minimal. The proc-macro = true declaration alone justifies has-build-exec.
The codebase was reviewed for unsafe, FFI, process spawning, network or filesystem I/O, environment variables, concurrency primitives, and cryptography. None was found, justifying uses-unsafe, uses-exec, uses-network, uses-filesystem, uses-environment, uses-concurrency, uses-crypto, uses-jit, and uses-interpreter, and likewise the corresponding implementation claims impl-crypto, impl-interpreter, impl-jit, impl-protocol, impl-datastructure, impl-algorithm, and impl-concurrency. The format-shorthand transformation in src/fmt.rs is a small text rewrite (~80 LOC), not parsing a data format into a structure, justifying impl-parser.
Three findings were recorded. FINDING-1 (medium, correctness) documents a real bug: any #[doc(...)] attribute with a non-NameValue shape on a Display-deriving type causes a proc-macro panic. The filter at src/attr.rs:72-85 selects every #[doc...] attribute but the subsequent match falls through to unimplemented!() for anything other than Meta::NameValue. Confirmed with a reproducer (tmp/repro/) using #[doc(hidden)]; output: error: proc-macro derive panicked ... = help: message: not implemented. The bug does not affect generated code — no crate compiles successfully — so it is a diagnostic/ergonomic issue, not a soundness hazard.
FINDING-2 (low, quality) notes two panic!/expect sites in src/attr.rs (lines 62, 110, 130) that should be syn::Error::new_spanned; the entry point at src/lib.rs:184 already wraps the result in to_compile_error(), so a structured error would yield a properly spanned diagnostic. FINDING-3 (low, quality) notes that the .stderr reference files referenced by tests/compile_tests.rs are excluded from the published crate via the include list, so the trybuild harness cannot validate expected error text downstream. The harness is gated to nightly via #[rustversion::attr(not(nightly), ignore)].
No malicious behaviour was identified, justifying is-benign.
Conclusion
displaydoc is a small (~900 LOC), focused procedural macro with a clear public API and a well-scoped dependency set (syn, quote, proc-macro2). The crate ships no build.rs, no binaries, no unsafe code, no I/O of any kind, and no network or filesystem touches; its only execution surface is the derive macro itself, which is a pure token-stream transformation. Tests cover the main code paths but include no fuzz or property tests for the format-shorthand parser. The one substantive finding (FINDING-1) is a panic on #[doc(hidden)] that produces a poor error message but cannot affect generated code; the other two findings are minor diagnostic and packaging quality issues.