broken link in proc-macro-generated doc referencing later-defined macro (--document-private-items)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Code
Reproduction Steps
git clone https://www.chiark.greenend.org.uk/ucgi/~ian/githttp/rust-experiments.git -b rustdoc-link-2026-06
cd rust-experiments
cargo doc --workspace --all-features --document-private-items
Expected Outcome
warning: unresolved link to `later`
Actual Output
No errors, but documentation has a broken link. To see the broken link:
- In your browser, visit the local path printed by the rustdoc rune
- Click on the entry for the macro
earlierderive_deftly_template_Earlier - Click on the word "Reference" (which is the start of the body of the doc comment)
- You're now visiting a file
.../rust-experiments/target/doc/foo/laterwhich does not exist
Version
rustdoc 1.96.0-beta.5 (a5a9a5438 2026-05-01)
Additional Details
Ordering is relevant
AFAICT the link is not resolved because it's a forward reference to a macro_rules macro. Swapping the definition of later to before Earlier makes the link resolve.
Exporting is might be relevant
Adding #[macro_export] to the definitions (via the export keyword to the derive-deflty call if necessary) makes it work.
But with the MCVE, it doesn't seem to make any difference.
Either spans, or merely the involvement of a proc macro, seem to be relevant
Update: for a repro without any external crates, see below.
I was not able to reproduce this without derive-deftly. The define_derive_deftly call in lib.rs expands to this:
#[doc = " Doc comment"] #[doc = ""] #[doc = " [Reference](later)"]
#[doc =
"\n\nThis is a `derive_deftly` template. Do not invoke it directly.\nTo use it, write: `#[derive(Deftly)] #[derive_deftly(Earlier)]`."]
macro_rules! derive_deftly_template_Earlier
{
[ actual macro body elided for clarity ]
}
You can get that output yourself with a rune like this:
RUSTFLAGS="--cfg derive_deftly_dprint" DERIVE_DEFTLY_DPRINT=1 cargo doc --workspace --all-features --document-private-items
But, when I replace the define_derive_deftly! call with a cut-and-paste of the whole expansion (as printed via the TokenStream's Display impl) the bug goes away: I get the warning as expected.
I experimented with replacing the define_derive_deftly call with a macro_rules macro whose expansion was a c&p of the derive-deftly output, but that also didn't repro the bug.
It may be relevant that for Reasons, derive-deftly respans its output using .resolved_at(Span::call_site) . For terminal TTs it then uses .set_span(). For groups it must use Group::new (via proc_macro2::Group::new). The precise code can be seen here https://gitlab.torproject.org/Diziet/rust-derive-deftly/-/blob/03493e38977328ce1cfd89bad38a868538479419/macros/utils.rs#L200
However, I don't think any of this should cause rustdoc to emit HTML containing broken links.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the linked rust-experiments branch using cargo doc --workspace --all-features --document-private-items, then inspect the generated page for the earlier macro and its later link. Compare the proc-macro expansion with the copied expansion and review derive-deftly's macros/utils.rs span handling. Done means rustdoc correctly resolves the forward reference or reports the broken link.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, documentation
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100