Skip to content

Commit 896dd83

Browse files
committed
Support multiple crate versions in --extern-html-root-url
1 parent 61d648f commit 896dd83

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

compiler/rustc_metadata/src/creader.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,14 @@ impl CStore {
261261
self.resolved_externs.insert(name, extern_crate);
262262
}
263263

264+
/// Crate resolved and loaded via the given extern name
265+
/// (corresponds to names in `sess.opts.externs`)
266+
///
267+
/// May be `None` if the crate wasn't used
268+
pub fn resolved_extern_crate(&self, externs_name: Symbol) -> Option<CrateNum> {
269+
self.resolved_externs.get(&externs_name).copied()
270+
}
271+
264272
pub(crate) fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> {
265273
self.metas
266274
.iter_enumerated()

src/doc/rustdoc/src/unstable-features.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ flags to control that behavior. When the `--extern-html-root-url` flag is given
395395
one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist
396396
in the output directory, those local docs will still override this flag.
397397

398+
The names in this flag are first matched against the names given in the `--extern name=` flags,
399+
which allows selecting between multiple crates with the same name (e.g. multiple versions of
400+
the same crate). For transitive dependencies that haven't been loaded via an `--extern` flag, matching
401+
falls backs to using crate names only, without ability to distinguish between multiple crates with
402+
the same name.
403+
398404
## `-Z force-unstable-if-unmarked`
399405

400406
Using this flag looks like this:

src/librustdoc/formats/cache.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_ast::join_path_syms;
44
use rustc_attr_data_structures::StabilityLevel;
55
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
66
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet};
7+
use rustc_metadata::creader::CStore;
78
use rustc_middle::ty::{self, TyCtxt};
89
use rustc_span::Symbol;
910
use tracing::debug;
@@ -158,18 +159,33 @@ impl Cache {
158159
assert!(cx.external_traits.is_empty());
159160
cx.cache.traits = mem::take(&mut krate.external_traits);
160161

162+
let render_options = &cx.render_options;
163+
let extern_url_takes_precedence = render_options.extern_html_root_takes_precedence;
164+
let dst = &render_options.output;
165+
166+
// Make `--extern-html-root-url` support the same names as `--extern` whenever possible
167+
let cstore = CStore::from_tcx(tcx);
168+
for (name, extern_url) in &render_options.extern_html_root_urls {
169+
if let Some(crate_num) = cstore.resolved_extern_crate(Symbol::intern(name)) {
170+
let e = ExternalCrate { crate_num };
171+
let location = e.location(Some(extern_url), extern_url_takes_precedence, dst, tcx);
172+
cx.cache.extern_locations.insert(e.crate_num, location);
173+
}
174+
}
175+
161176
// Cache where all our extern crates are located
162-
// FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
177+
// This is also used in the JSON output.
163178
for &crate_num in tcx.crates(()) {
164179
let e = ExternalCrate { crate_num };
165180

166181
let name = e.name(tcx);
167-
let render_options = &cx.render_options;
168-
let extern_url = render_options.extern_html_root_urls.get(name.as_str()).map(|u| &**u);
169-
let extern_url_takes_precedence = render_options.extern_html_root_takes_precedence;
170-
let dst = &render_options.output;
171-
let location = e.location(extern_url, extern_url_takes_precedence, dst, tcx);
172-
cx.cache.extern_locations.insert(e.crate_num, location);
182+
cx.cache.extern_locations.entry(e.crate_num).or_insert_with(|| {
183+
// falls back to matching by crates' own names, because
184+
// transitive dependencies and injected crates may be loaded without `--extern`
185+
let extern_url =
186+
render_options.extern_html_root_urls.get(name.as_str()).map(|u| &**u);
187+
e.location(extern_url, extern_url_takes_precedence, dst, tcx)
188+
});
173189
cx.cache.external_paths.insert(e.def_id(), (vec![name], ItemType::Module));
174190
}
175191

0 commit comments

Comments
 (0)