Skip to content

Commit 2e1b954

Browse files
committed
rustdoc-json: add rlib path to ExternalCrate to enable robust crate resolution
Historically, it's not been possible to robustly resolve a cross-crate item in rustdoc-json. If you had a `Id` that wasn't in `Crate::index` (because it was defined in a different crate), you could only look it up it `Crate::paths`. But there, you don't get the full information, only an `ItemSummary`. This tells you the `path` and the `crate_id`. But knowing the `crate_id` isn't enough to be able to build/find the rustdoc-json output with this item. It's only use is to get a `ExternalCrate` (via `Crate::external_crates`). But that only tells you the `name` (as a string). This isn't enough to uniquely identify a crate, as there could be multiple versions/features [1] [2]. This was originally proposed to be solved via LukeMathWalker's `--orchestrator-id` proposal (https://www.github.com/rust-lang/compiler-team/issues/635). But that requires invasive changes to cargo/rustc. This PR instead implements Urgau's proposal to re-use the path to a crate's rmeta/rlib as a unique identifer. Callers can use that to determine which package it corresponds to in the language of the build-system above rustc. E.g. for cargo, `cargo rustdoc --message-format=json --output-format=json -Zunstable-options`). (Once you've found the right external crate's rustdoc-json output, you still need to resolve the path->id in that crate. But that's """just""" a matter of walking the module tree. We should probably still make that nicer (by, for example, allowing sharing `Id`s between rustdoc-json document), but that's a future concern) For some notes from RustWeek 2025, where this was designed, see https://hackmd.io/0jkdguobTnW7nXoGKAxfEQ [1]: https://www.github.com/rust-lang/compiler-team/issues/635#issue-1714254865 § Problem [2]: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/Identifying.20external.20crates.20in.20Rustdoc.20JSON/with/352701211
1 parent 0df64c5 commit 2e1b954

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

src/librustdoc/json/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,13 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
302302
ExternalLocation::Remote(s) => Some(s.clone()),
303303
_ => None,
304304
},
305+
path: self
306+
.tcx
307+
.used_crate_source(*crate_num)
308+
.paths()
309+
.next()
310+
.expect("crate should have at least 1 path")
311+
.clone(),
305312
},
306313
)
307314
})
@@ -339,20 +346,21 @@ mod size_asserts {
339346
// tidy-alphabetical-start
340347
static_assert_size!(AssocItemConstraint, 112);
341348
static_assert_size!(Crate, 184);
342-
static_assert_size!(ExternalCrate, 48);
343349
static_assert_size!(FunctionPointer, 168);
344350
static_assert_size!(GenericArg, 80);
345351
static_assert_size!(GenericArgs, 104);
346352
static_assert_size!(GenericBound, 72);
347353
static_assert_size!(GenericParamDef, 136);
348354
static_assert_size!(Impl, 304);
349-
// `Item` contains a `PathBuf`, which is different sizes on different OSes.
350-
static_assert_size!(Item, 528 + size_of::<std::path::PathBuf>());
351355
static_assert_size!(ItemSummary, 32);
352356
static_assert_size!(PolyTrait, 64);
353357
static_assert_size!(PreciseCapturingArg, 32);
354358
static_assert_size!(TargetFeature, 80);
355359
static_assert_size!(Type, 80);
356360
static_assert_size!(WherePredicate, 160);
357361
// tidy-alphabetical-end
362+
363+
// These contains a `PathBuf`, which is different sizes on different OSes.
364+
static_assert_size!(Item, 528 + size_of::<std::path::PathBuf>());
365+
static_assert_size!(ExternalCrate, 48 + size_of::<std::path::PathBuf>());
358366
}

src/rustdoc-json-types/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
3737
// will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line
3838
// are deliberately not in a doc comment, because they need not be in public docs.)
3939
//
40-
// Latest feature: Add `ItemKind::Attribute`.
41-
pub const FORMAT_VERSION: u32 = 56;
40+
// Latest feature: Add `ExternCrate::path`.
41+
pub const FORMAT_VERSION: u32 = 57;
4242

4343
/// The root of the emitted JSON blob.
4444
///
@@ -135,6 +135,8 @@ pub struct ExternalCrate {
135135
pub name: String,
136136
/// The root URL at which the crate's documentation lives.
137137
pub html_root_url: Option<String>,
138+
139+
pub path: PathBuf,
138140
}
139141

140142
/// Information about an external (not defined in the local crate) [`Item`].

0 commit comments

Comments
 (0)