diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index da6840c72f5b1..a4cbef8c39177 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -24,6 +24,7 @@ use tracing::instrument;
use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate};
use crate::clean::{self, utils};
+use crate::config::ShouldMerge;
use crate::error::Error;
use crate::formats::cache::{Cache, OrphanImplItem};
use crate::formats::item_type::ItemType;
@@ -721,7 +722,9 @@ impl SerializedSearchIndex {
}
},
),
- self.alias_pointers[id].and_then(|alias| map.get(&alias).copied()),
+ self.alias_pointers[id].and_then(|alias| {
+ if self.names[alias].is_empty() { None } else { map.get(&alias).copied() }
+ }),
);
}
new.generic_inverted_index = self
@@ -1248,6 +1251,7 @@ pub(crate) fn build_index(
tcx: TyCtxt<'_>,
doc_root: &Path,
resource_suffix: &str,
+ should_merge: &ShouldMerge,
) -> Result {
let mut search_index = std::mem::take(&mut cache.search_index);
@@ -1298,7 +1302,11 @@ pub(crate) fn build_index(
//
// if there's already a search index, load it into memory and add the new entries to it
// otherwise, do nothing
- let mut serialized_index = SerializedSearchIndex::load(doc_root, resource_suffix)?;
+ let mut serialized_index = if should_merge.read_rendered_cci {
+ SerializedSearchIndex::load(doc_root, resource_suffix)?
+ } else {
+ SerializedSearchIndex::default()
+ };
// The crate always goes first in this list
let crate_name = krate.name(tcx);
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 9a8df53931394..6bf116c3b75ad 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -66,8 +66,14 @@ pub(crate) fn write_shared(
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
- let search_index =
- build_index(krate, &mut cx.shared.cache, tcx, &cx.dst, &cx.shared.resource_suffix)?;
+ let search_index = build_index(
+ krate,
+ &mut cx.shared.cache,
+ tcx,
+ &cx.dst,
+ &cx.shared.resource_suffix,
+ &opt.should_merge,
+ )?;
let crate_name = krate.name(cx.tcx());
let crate_name = crate_name.as_str(); // rand
diff --git a/tests/run-make/rustdoc-merge-directory-alias/dep1.rs b/tests/run-make/rustdoc-merge-directory-alias/dep1.rs
new file mode 100644
index 0000000000000..b62f31c982b7f
--- /dev/null
+++ b/tests/run-make/rustdoc-merge-directory-alias/dep1.rs
@@ -0,0 +1,10 @@
+pub struct Dep1;
+pub struct Dep2;
+pub struct Dep3;
+pub struct Dep4;
+
+//@ hasraw crates.js 'dep1'
+//@ hasraw search.index/name/*.js 'Dep1'
+//@ has dep1/index.html
+#[doc(alias = "dep1_missing")]
+pub struct Dep5;
diff --git a/tests/run-make/rustdoc-merge-directory-alias/dep2.rs b/tests/run-make/rustdoc-merge-directory-alias/dep2.rs
new file mode 100644
index 0000000000000..2df4452413c21
--- /dev/null
+++ b/tests/run-make/rustdoc-merge-directory-alias/dep2.rs
@@ -0,0 +1,4 @@
+//@ hasraw crates.js 'dep2'
+//@ hasraw search.index/name/*.js 'Second'
+//@ has dep2/index.html
+pub struct Second;
diff --git a/tests/run-make/rustdoc-merge-directory-alias/dep_missing.rs b/tests/run-make/rustdoc-merge-directory-alias/dep_missing.rs
new file mode 100644
index 0000000000000..74236aef47ea5
--- /dev/null
+++ b/tests/run-make/rustdoc-merge-directory-alias/dep_missing.rs
@@ -0,0 +1,4 @@
+//@ !hasraw crates.js 'dep_missing'
+//@ !hasraw search.index/name/*.js 'DepMissing'
+//@ has dep_missing/index.html
+pub struct DepMissing;
diff --git a/tests/run-make/rustdoc-merge-directory-alias/rmake.rs b/tests/run-make/rustdoc-merge-directory-alias/rmake.rs
new file mode 100644
index 0000000000000..096eb4a487c15
--- /dev/null
+++ b/tests/run-make/rustdoc-merge-directory-alias/rmake.rs
@@ -0,0 +1,88 @@
+// Running --merge=finalize without an input crate root should not trigger ICE.
+// Issue: https://github.com/rust-lang/rust/issues/146646
+
+//@ needs-target-std
+
+use run_make_support::{htmldocck, path, rustdoc};
+
+fn main() {
+ let out_dir = path("out");
+ let merged_dir = path("merged");
+ let parts_out_dir = path("parts");
+
+ rustdoc()
+ .input("dep1.rs")
+ .out_dir(&out_dir)
+ .arg("-Zunstable-options")
+ .arg(format!("--parts-out-dir={}", parts_out_dir.display()))
+ .arg("--merge=none")
+ .run();
+ assert!(parts_out_dir.join("dep1.json").exists());
+
+ let output = rustdoc()
+ .arg("-Zunstable-options")
+ .out_dir(&out_dir)
+ .arg(format!("--include-parts-dir={}", parts_out_dir.display()))
+ .arg("--merge=finalize")
+ .run();
+ output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug.");
+
+ rustdoc()
+ .input("dep2.rs")
+ .out_dir(&out_dir)
+ .arg("-Zunstable-options")
+ .arg(format!("--parts-out-dir={}", parts_out_dir.display()))
+ .arg("--merge=none")
+ .run();
+ assert!(parts_out_dir.join("dep2.json").exists());
+
+ let output2 = rustdoc()
+ .arg("-Zunstable-options")
+ .out_dir(&out_dir)
+ .arg(format!("--include-parts-dir={}", parts_out_dir.display()))
+ .arg("--merge=finalize")
+ .run();
+ output2.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug.");
+
+ rustdoc()
+ .input("dep1.rs")
+ .out_dir(&out_dir)
+ .arg("-Zunstable-options")
+ .arg(format!("--parts-out-dir={}", parts_out_dir.display()))
+ .arg("--merge=none")
+ .run();
+ assert!(parts_out_dir.join("dep1.json").exists());
+
+ let output3 = rustdoc()
+ .arg("-Zunstable-options")
+ .out_dir(&out_dir)
+ .arg(format!("--include-parts-dir={}", parts_out_dir.display()))
+ .arg("--merge=finalize")
+ .run();
+ output3.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug.");
+
+ // dep_missing is different, because --parts-out-dir is not supplied
+ rustdoc().input("dep_missing.rs").out_dir(&out_dir).run();
+ assert!(parts_out_dir.join("dep2.json").exists());
+
+ rustdoc()
+ .input("dep1.rs")
+ .out_dir(&out_dir)
+ .arg("-Zunstable-options")
+ .arg(format!("--parts-out-dir={}", parts_out_dir.display()))
+ .arg("--merge=none")
+ .run();
+ assert!(parts_out_dir.join("dep1.json").exists());
+
+ let output4 = rustdoc()
+ .arg("-Zunstable-options")
+ .out_dir(&out_dir)
+ .arg(format!("--include-parts-dir={}", parts_out_dir.display()))
+ .arg("--merge=finalize")
+ .run();
+ output4.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug.");
+
+ htmldocck().arg(&out_dir).arg("dep1.rs").run();
+ htmldocck().arg(&out_dir).arg("dep2.rs").run();
+ htmldocck().arg(&out_dir).arg("dep_missing.rs").run();
+}