Subject
async-trait is dtolnay's compiler-plugin-flavoured proc-macro attribute
that rewrites async fn items inside Rust trait definitions and impl
blocks into fns returning Pin<Box<dyn Future + Send + 'async_trait>>.
This restores object safety (dyn Trait) for traits that contain async
methods — a niche that the language's stabilised async fn in trait
(Rust 1.75) deliberately does not cover. The crate is used pervasively
across the async Rust ecosystem.
Methodology
The published crate was diffed against the upstream Git checkout at the
commit recorded in .cargo_vcs_info.json. All ten source files in src/
(~1400 lines) were read or surveyed; the proc-macro entry point in
src/lib.rs was read in full and the rewriting core in src/expand.rs
was inspected. The integration-test crate (tests/test.rs, 1728 lines)
and the trybuild UI suite (tests/compiletest.rs plus 16 cases under
tests/ui/) were noted. The crate was scanned for unsafe, extern,
build scripts, filesystem/env/network/process usage, and binary
artefacts.
Results
All source and test files are byte-identical between the published crate
and upstream. Cargo.toml differences are limited to cargo's standard
normalisation; the upstream build.rs is correctly omitted from the
published crate by an explicit exclude = ["build.rs"] (the published
build = false confirms cargo did not interpret it as a build script).
The upstream build.rs itself only emits two cargo: directives
(rerun-if-changed and rustc-check-cfg) and is not reachable from a
consumer's compile, so its content doesn't matter for the audit.
[lib] proc-macro = true makes the crate a proc-macro, which runs at
compile time on every downstream consumer's machine — this is the
primary reason has-build-exec is true. No build.rs runs (it is
excluded from the published artefact), and the crate ships no binary
artefacts or post-install scripts, justifying has-binaries and
has-install-exec. The build-exec attack surface is the proc-macro itself.
The proc-macro exports one attribute, #[async_trait] (with an optional
(?Send) argument). Its implementation is pure token rewriting over
syn/quote/proc-macro2 ASTs: parsing a Trait or Impl item,
collecting elided/explicit lifetimes, rewriting async fn signatures to
the boxed-future form, replacing self references inside method bodies
as appropriate, and re-emitting tokens. No unsafe blocks appear
anywhere in src/; the only token-level mention of unsafe is parsing
for the keyword in trait-item signatures (src/parse.rs). The crate's
own documentation guarantees that the expanded code is safe Rust as
well, justifying uses-unsafe.
No filesystem reads, no environment-variable access, no
std::process::Command, and no networking primitives appear in the
codebase — the only std imports are std::collections::BTreeSet and
std::mem. The proc-macro is therefore deterministic and
side-effect-free, justifying build-exec-safe, build-exec-deterministic,
build-exec-no-network, build-exec-no-write-out, build-exec-minimal,
and is-benign. The codebase was reviewed for cryptographic, network,
filesystem, environment, exec, JIT, interpreter, concurrency, and
unsafe usage, and none was found, justifying uses-network,
uses-filesystem, uses-environment, uses-exec, uses-crypto,
uses-jit, uses-interpreter, uses-concurrency, impl-crypto,
impl-parser, impl-interpreter, impl-jit, impl-protocol,
impl-datastructure, impl-algorithm, impl-concurrency.
Testing is supplied by tests/test.rs (1728 lines), a comprehensive
integration suite covering every combination the macro is meant to
handle: by-value/by-ref/by-mut-ref/no self; generics; explicit and
elided lifetimes; associated types; default-body methods; non-Send
mode (?Send); supertraits; mixing async and sync methods; and so on.
A compiletest.rs harness drives trybuild over 16 expected-failure
cases under tests/ui/, which capture the error spans the macro emits
for misuse. There are no in-source #[test] blocks (has-unit-tests),
no fuzz, and no property tests (has-fuzz-tests, has-property-tests).
No findings were recorded.
Conclusion
async-trait is a mature, well-tested proc-macro whose entire surface
is mechanical token rewriting with no I/O, no network, no environment
reads, no unsafe, and no binary artefacts. The published crate
correctly excludes its upstream build.rs. No security, safety,
correctness, or quality concerns were identified.