Skip to content

Commit b1928aa

Browse files
committed
Auto merge of #82776 - jyn514:extern-url-fallback, r=GuillaumeGomez
Give precedence to `html_root_url` over `--extern-html-root-url` by default, but add a way to opt-in to the previous behavior ## What is an HTML root url? It tells rustdoc where it should link when documentation for a crate is not available locally; for example, when a crate is a dependency of a crate documented with `cargo doc --no-deps`. ## What is the difference between `html_root_url` and `--extern-html-root-url`? Both of these tell rustdoc what the HTML root should be set to. `doc(html_root_url)` is set by the crate author, while `--extern-html-root-url` is set by the person documenting the crate. These are often different. For example, docs.rs uses `--extern-html-root-url https://docs.rs/crate-name/version` to ensure all crates have documentation, even if `html_root_url` is not set. Conversely, crates such as Rocket set `doc(html_root_url = "https://api.rocket.rs")`, because they prefer users to view the documentation on their own site. Crates also set `html_root_url` to ensure they have documentation when building locally when offline. This is unfortunate to require, because it's more work from the library author. It also makes it impossible to distinguish between crates that want to be viewed on a different site (e.g. Rocket) and crates that just want documentation to be visible offline at all (e.g. Tokio). I have authored a separate change to the API guidelines to no longer recommend doing this: rust-lang/api-guidelines#230. ## Why change the default? In the past, docs.rs has been the main user of `--extern-html-root-url`. However, it's useful for other projects as well. In particular, Cargo wants to pass it by default when running `--no-deps` (rust-lang/cargo#8296). Unfortunately, for these other use cases, the priority order is inverted. They want to give *precedence* to the URL the crate picks, and only fall back to the `--extern-html-root` if no `html_root_url` is present. That allows passing `--extern-html-root` unconditionally, without having to parse the source code to see what attributes are present. For docs.rs, however, we still want to keep the old behavior, so that all links on docs.rs stay on the site.
2 parents 99b73e8 + 18f0f24 commit b1928aa

File tree

9 files changed

+51
-14
lines changed

9 files changed

+51
-14
lines changed

src/librustdoc/clean/types.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ impl ExternalCrate {
168168
crate fn location(
169169
&self,
170170
extern_url: Option<&str>,
171+
extern_url_takes_precedence: bool,
171172
dst: &std::path::Path,
172173
tcx: TyCtxt<'_>,
173174
) -> ExternalLocation {
@@ -189,8 +190,10 @@ impl ExternalCrate {
189190
return Local;
190191
}
191192

192-
if let Some(url) = extern_url {
193-
return to_remote(url);
193+
if extern_url_takes_precedence {
194+
if let Some(url) = extern_url {
195+
return to_remote(url);
196+
}
194197
}
195198

196199
// Failing that, see if there's an attribute specifying where to find this
@@ -202,6 +205,7 @@ impl ExternalCrate {
202205
.filter_map(|a| a.value_str())
203206
.map(to_remote)
204207
.next()
208+
.or(extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
205209
.unwrap_or(Unknown) // Well, at least we tried.
206210
}
207211

src/librustdoc/config.rs

+5
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ crate struct RenderOptions {
233233
crate extension_css: Option<PathBuf>,
234234
/// A map of crate names to the URL to use instead of querying the crate's `html_root_url`.
235235
crate extern_html_root_urls: BTreeMap<String, String>,
236+
/// Whether to give precedence to `html_root_url` or `--exten-html-root-url`.
237+
crate extern_html_root_takes_precedence: bool,
236238
/// A map of the default settings (values are as for DOM storage API). Keys should lack the
237239
/// `rustdoc-` prefix.
238240
crate default_settings: FxHashMap<String, String>,
@@ -658,6 +660,8 @@ impl Options {
658660
let show_type_layout = matches.opt_present("show-type-layout");
659661
let nocapture = matches.opt_present("nocapture");
660662
let generate_link_to_definition = matches.opt_present("generate-link-to-definition");
663+
let extern_html_root_takes_precedence =
664+
matches.opt_present("extern-html-root-takes-precedence");
661665

662666
if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) {
663667
diag.struct_err(
@@ -714,6 +718,7 @@ impl Options {
714718
themes,
715719
extension_css,
716720
extern_html_root_urls,
721+
extern_html_root_takes_precedence,
717722
default_settings,
718723
resource_suffix,
719724
enable_minification,

src/librustdoc/core.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -528,9 +528,7 @@ crate fn run_global_ctxt(
528528

529529
let render_options = ctxt.render_options;
530530
let mut cache = ctxt.cache;
531-
krate = tcx.sess.time("create_format_cache", || {
532-
cache.populate(krate, tcx, &render_options.extern_html_root_urls, &render_options.output)
533-
});
531+
krate = tcx.sess.time("create_format_cache", || cache.populate(krate, tcx, &render_options));
534532

535533
// The main crate doc comments are always collapsed.
536534
krate.collapsed = true;

src/librustdoc/formats/cache.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use std::collections::BTreeMap;
21
use std::mem;
3-
use std::path::Path;
42

53
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
64
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
@@ -9,6 +7,7 @@ use rustc_middle::ty::TyCtxt;
97
use rustc_span::symbol::sym;
108

119
use crate::clean::{self, GetDefId, ItemId};
10+
use crate::config::RenderOptions;
1211
use crate::fold::DocFolder;
1312
use crate::formats::item_type::ItemType;
1413
use crate::formats::Impl;
@@ -142,19 +141,21 @@ impl Cache {
142141
&mut self,
143142
mut krate: clean::Crate,
144143
tcx: TyCtxt<'_>,
145-
extern_html_root_urls: &BTreeMap<String, String>,
146-
dst: &Path,
144+
render_options: &RenderOptions,
147145
) -> clean::Crate {
148146
// Crawl the crate to build various caches used for the output
149147
debug!(?self.crate_version);
150148
self.traits = krate.external_traits.take();
149+
let RenderOptions { extern_html_root_takes_precedence, output: dst, .. } = render_options;
151150

152151
// Cache where all our extern crates are located
153152
// FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
154153
for &e in &krate.externs {
155154
let name = e.name(tcx);
156-
let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
157-
self.extern_locations.insert(e.crate_num, e.location(extern_url, &dst, tcx));
155+
let extern_url =
156+
render_options.extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
157+
let location = e.location(extern_url, *extern_html_root_takes_precedence, dst, tcx);
158+
self.extern_locations.insert(e.crate_num, location);
158159
self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
159160
}
160161

src/librustdoc/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,13 @@ fn opts() -> Vec<RustcOptGroup> {
294294
"NAME=URL",
295295
)
296296
}),
297+
unstable("extern-html-root-takes-precedence", |o| {
298+
o.optflagmulti(
299+
"",
300+
"extern-html-root-takes-precedence",
301+
"give precedence to `--extern-html-root-url`, not `html_root_url`",
302+
)
303+
}),
297304
stable("plugin-path", |o| o.optmulti("", "plugin-path", "removed", "DIR")),
298305
stable("C", |o| {
299306
o.optmulti("C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]")
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#![doc(html_root_url="https://example.com/html_root")]
2+
pub fn foo() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn bar() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compile-flags:-Z unstable-options --extern-html-root-url core=https://example.com/core/0.1.0 --extern-html-root-takes-precedence
2+
3+
// @has extern_html_root_url_precedence/index.html
4+
// --extern-html-root should take precedence if `--takes-precedence` is passed
5+
// @has - '//a/@href' 'https://example.com/core/0.1.0/core/iter/index.html'
6+
#[doc(no_inline)]
7+
pub use std::iter;
+15-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
1-
// compile-flags:-Z unstable-options --extern-html-root-url core=https://example.com/core/0.1.0
1+
// compile-flags:-Z unstable-options --extern-html-root-url html_root=https://example.com/override --extern-html-root-url no_html_root=https://example.com/override
2+
// aux-build:html_root.rs
3+
// aux-build:no_html_root.rs
4+
// NOTE: intentionally does not build any auxiliary docs
5+
6+
extern crate html_root;
7+
extern crate no_html_root;
28

39
// @has extern_html_root_url/index.html
4-
// @has - '//a/@href' 'https://example.com/core/0.1.0/core/iter/index.html'
10+
// `html_root_url` should override `--extern-html-root-url`
11+
// @has - '//a/@href' 'https://example.com/html_root/html_root/fn.foo.html'
12+
#[doc(no_inline)]
13+
pub use html_root::foo;
14+
515
#[doc(no_inline)]
6-
pub use std::iter;
16+
// `--extern-html-root-url` should apply if no `html_root_url` is given
17+
// @has - '//a/@href' 'https://example.com/override/no_html_root/fn.bar.html'
18+
pub use no_html_root::bar;

0 commit comments

Comments
 (0)