Skip to content

rustdoc-json: multiple package versions clobber their output paths #142370

Open

Description

@kornelski

Rustdoc uses crate name as a base for file names (target/doc/$name.json), but this naming scheme is incompatible with Cargo projects where names are not unique, and multiple different crates can have the same name.

[package]
name = "exampledoc" # try `name = "wild"` for extra difficulty
edition = "2024"

[dependencies]
old = { package = "wild", version = "1" }
new = { package = "wild", version = "2" }
pub use ::old;
pub use ::new;
RUSTDOCFLAGS="-Z unstable-options --output-format=json" cargo +nightly doc

This ends up writing target/doc/wild.json for only one of the two versions. The same problem can happen if Cargo has git, path, or custom registry dependencies that use names overlapping with crates-io dependencies, so even name + version isn't unique.

Using the package alias (new and old in this example) wouldn't be sufficient, because these aliases aren't globally unique either. Different crates in the same dependency tree can rename different deps to the same name.


cargo 1.89.0-nightly (fc1518ef0 2025-06-06)

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jun 11, 2025
  2. bjorn3 commented on Jun 11, 2025

    @bjorn3
    Member

    Doesn't the same happen for the html docs?

  3. kornelski commented on Jun 11, 2025

    @kornelski
    ContributorAuthor

    Yes, the same happens to HTML docs, but the trade-offs are different for JSON.

    JSON is consumed by tooling like cargo-semver-checks, which doesn't need the paths to be pretty and URL-safe, but needs the data to be reliable and unambiguous.

    I think for tooling a relatively simple and robust solution would be to place the json files next to their .rmeta files. Rustdoc gets args like:

    --extern old=target/debug/deps/libwild-ad0b5e70d004f3ed.rmeta 
    --extern new=target/debug/deps/libwild-a292fc321d43c842.rmeta
    

    and could write:

    target/debug/deps/libwild-ad0b5e70d004f3ed.rustdoc.json 
    target/debug/deps/libwild-a292fc321d43c842.rustdoc.json 
    

    These rmeta paths are present in --message-format=json output of cargo doc, and could be used to map back to Cargo's unique pkgid.

  4. added
    T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jun 11, 2025
  5. aDotInTheVoid commented on Jun 11, 2025

    @aDotInTheVoid
    Member
  6. obi1kenobi commented on Jun 11, 2025

    @obi1kenobi
    Member

    My top concern is not accidentally blocking the work on cross-crate rustdoc JSON linking by a change made here. At RustWeek we discussed a variety of options about that, some of which also involved .rmeta and --message-format=json, and I worry that we might accidentally make mutually-incompatible choices that may be hard to reverse.

    From cargo-semver-checks' perspective, the clobbering is a known issue that doesn't affect us at all at the moment. It'll obviously be a bigger concern once we have multiple rustdoc JSON files to connect, which is why in my mind this issue is a sub-issue of that bigger piece of work.

  7. LukeMathWalker commented on Jun 12, 2025

    @LukeMathWalker
    Contributor

    Naming collisions in rustdoc-json are a known (and annoying) issue for Pavex.
    The downsides are multiple:

    • We need to maintain extra logic to compute JSON docs in batches that are collision-free.
    • We can't (yet) rely on cargo's caching logic since it can confuse the docs for two different versions of the same crate thus skipping a recompute that would instead be needed.
    • The two issues above, combined, have an impact on our performance, since generating rustdoc's JSON docs is by far the task we spend most time on.

    Having said all that, I agree with @obi1kenobi—I believe we should strive for a structural solution that we aim to stabilize, while taking into account the other ambiguity issue we're dealing with in rustdoc-json. The two things don't necessarily have to be solved by the same mechanism, but I'd like to have a shared agreement as to what the two solutions will look like to confirm they're compatible before moving on either one.

    Specifically on the .rmeta proposal: assuming that tooling can be informed by cargo as to what path will be used (via --message-format=json, I assume?), I think this would be viable.
    My only concern would be in using a naming scheme that's highly not-human-friendly. It's not an issue for .rmeta, since they are an intermediate build artifact, but I consider the JSON documents to be output artifacts. Nonetheless, they're geared towards tooling consumers, so that may not be a significant issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-rustdoc-jsonArea: Rustdoc JSON backendC-bugCategory: This is a bug.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions