Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 87 additions & 79 deletions src/librustdoc/html/render/search_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,29 @@ impl SerializedSearchIndex {
let other_entryid_offset = self.names.len();
let mut map_other_pathid_to_self_pathid = Vec::new();
let mut skips = FxHashSet::default();

fn remap_entry_data(
other_entry_data: &EntryData,
map_other_pathid_to_self_pathid: &[usize],
) -> EntryData {
EntryData {
parent: other_entry_data
.parent
.map(|parent| map_other_pathid_to_self_pathid[parent])
.clone(),
module_path: other_entry_data
.module_path
.map(|path| map_other_pathid_to_self_pathid[path])
.clone(),
exact_module_path: other_entry_data
.exact_module_path
.map(|exact_path| map_other_pathid_to_self_pathid[exact_path])
.clone(),
krate: map_other_pathid_to_self_pathid[other_entry_data.krate],
..other_entry_data.clone()
}
}

for (other_pathid, other_path_data) in other.path_data.iter().enumerate() {
if let Some(other_path_data) = other_path_data {
let name = Symbol::intern(&other.names[other_pathid]);
Expand Down Expand Up @@ -439,87 +462,72 @@ impl SerializedSearchIndex {
}
}
for other_entryid in 0..other.names.len() {
if skips.contains(&other_entryid) {
// we push tombstone entries to keep the IDs lined up
self.push(String::new(), None, None, String::new(), None, None, None);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it, the only change is the behavior in this case, instead of having everything be a default value, instead only path_data is None, and everything else retains its normal value?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. That’s the fix. Everything else is test cases.

} else {
self.push(
other.names[other_entryid].clone(),
other.path_data[other_entryid].clone(),
other.entry_data[other_entryid].as_ref().map(|other_entry_data| EntryData {
parent: other_entry_data
.parent
.map(|parent| map_other_pathid_to_self_pathid[parent])
.clone(),
module_path: other_entry_data
.module_path
.map(|path| map_other_pathid_to_self_pathid[path])
.clone(),
exact_module_path: other_entry_data
.exact_module_path
.map(|exact_path| map_other_pathid_to_self_pathid[exact_path])
.clone(),
krate: map_other_pathid_to_self_pathid[other_entry_data.krate],
..other_entry_data.clone()
}),
other.descs[other_entryid].clone(),
other.function_data[other_entryid].clone().map(|mut func| {
fn map_fn_sig_item(
map_other_pathid_to_self_pathid: &Vec<usize>,
ty: &mut RenderType,
) {
match ty.id {
None => {}
Some(RenderTypeId::Index(generic)) if generic < 0 => {}
Some(RenderTypeId::Index(id)) => {
let id = usize::try_from(id).unwrap();
let id = map_other_pathid_to_self_pathid[id];
assert!(id != !0);
ty.id = Some(RenderTypeId::Index(isize::try_from(id).unwrap()));
}
_ => unreachable!(),
self.push(
other.names[other_entryid].clone(),
if skips.contains(&other_entryid) {
None
} else {
other.path_data[other_entryid].clone()
},
other.entry_data[other_entryid].as_ref().map(|other_entry_data| {
remap_entry_data(other_entry_data, &map_other_pathid_to_self_pathid)
}),
other.descs[other_entryid].clone(),
other.function_data[other_entryid].clone().map(|mut func| {
fn map_fn_sig_item(
map_other_pathid_to_self_pathid: &Vec<usize>,
ty: &mut RenderType,
) {
match ty.id {
None => {}
Some(RenderTypeId::Index(generic)) if generic < 0 => {}
Some(RenderTypeId::Index(id)) => {
let id = usize::try_from(id).unwrap();
let id = map_other_pathid_to_self_pathid[id];
assert!(id != !0);
ty.id = Some(RenderTypeId::Index(isize::try_from(id).unwrap()));
}
if let Some(generics) = &mut ty.generics {
for generic in generics {
map_fn_sig_item(map_other_pathid_to_self_pathid, generic);
}
_ => unreachable!(),
}
if let Some(generics) = &mut ty.generics {
for generic in generics {
map_fn_sig_item(map_other_pathid_to_self_pathid, generic);
}
if let Some(bindings) = &mut ty.bindings {
for (param, constraints) in bindings {
*param = match *param {
param @ RenderTypeId::Index(generic) if generic < 0 => {
param
}
RenderTypeId::Index(id) => {
let id = usize::try_from(id).unwrap();
let id = map_other_pathid_to_self_pathid[id];
assert!(id != !0);
RenderTypeId::Index(isize::try_from(id).unwrap())
}
_ => unreachable!(),
};
for constraint in constraints {
map_fn_sig_item(
map_other_pathid_to_self_pathid,
constraint,
);
}
if let Some(bindings) = &mut ty.bindings {
for (param, constraints) in bindings {
*param = match *param {
param @ RenderTypeId::Index(generic) if generic < 0 => param,
RenderTypeId::Index(id) => {
let id = usize::try_from(id).unwrap();
let id = map_other_pathid_to_self_pathid[id];
assert!(id != !0);
RenderTypeId::Index(isize::try_from(id).unwrap())
}
_ => unreachable!(),
};
for constraint in constraints {
map_fn_sig_item(map_other_pathid_to_self_pathid, constraint);
}
}
}
for input in &mut func.inputs {
map_fn_sig_item(&map_other_pathid_to_self_pathid, input);
}
for output in &mut func.output {
map_fn_sig_item(&map_other_pathid_to_self_pathid, output);
}
for clause in &mut func.where_clause {
for entry in clause {
map_fn_sig_item(&map_other_pathid_to_self_pathid, entry);
}
}
for input in &mut func.inputs {
map_fn_sig_item(&map_other_pathid_to_self_pathid, input);
}
for output in &mut func.output {
map_fn_sig_item(&map_other_pathid_to_self_pathid, output);
}
for clause in &mut func.where_clause {
for entry in clause {
map_fn_sig_item(&map_other_pathid_to_self_pathid, entry);
}
func
}),
}
func
}),
if skips.contains(&other_entryid) {
None
} else {
other.type_data[other_entryid].as_ref().map(|type_data| TypeData {
inverted_function_inputs_index: type_data
.inverted_function_inputs_index
Expand Down Expand Up @@ -556,11 +564,11 @@ impl SerializedSearchIndex {
})
.collect(),
search_unbox: type_data.search_unbox,
}),
other.alias_pointers[other_entryid]
.map(|alias_pointer| alias_pointer + other_entryid_offset),
);
}
})
},
other.alias_pointers[other_entryid]
.map(|alias_pointer| alias_pointer + other_entryid_offset),
);
}
if other.generic_inverted_index.len() > self.generic_inverted_index.len() {
self.generic_inverted_index.resize(other.generic_inverted_index.len(), Vec::new());
Expand Down
15 changes: 10 additions & 5 deletions src/librustdoc/html/render/write_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,15 +375,20 @@ impl CrateInfo {
.fold(Ok(Vec::new()), |acc, parts_path| {
let mut acc = acc?;
let dir = &parts_path.0;
acc.append(&mut try_err!(std::fs::read_dir(dir), dir.as_path())
let mut files: Vec<Result<PathBuf, std::io::Error>> = try_err!(std::fs::read_dir(dir), dir.as_path())
.map(|file| Ok(file?.path()))
.collect();
files.sort_by_key(|p| p.as_ref().map_or(PathBuf::new(), |p| p.clone()));
acc.append(&mut files
.into_iter()
.filter_map(|file| {
let to_crate_info = |file: Result<std::fs::DirEntry, std::io::Error>| -> Result<Option<CrateInfo>, Error> {
let to_crate_info = |file: Result<PathBuf, std::io::Error>| -> Result<Option<CrateInfo>, Error> {
let file = try_err!(file, dir.as_path());
if file.path().extension() != Some(OsStr::new("json")) {
if file.extension() != Some(OsStr::new("json")) {
return Ok(None);
}
let parts = try_err!(fs::read(file.path()), file.path());
let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), file.path());
let parts = try_err!(fs::read(&file), &file);
let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &file);
Ok(Some(parts))
};
to_crate_info(file).transpose()
Expand Down
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ pub(crate) struct TestProps {
pub(crate) disable_gdb_pretty_printers: bool,
/// Compare the output by lines, rather than as a single string.
pub(crate) compare_output_by_lines: bool,
/// Use CCI (`--read-doc-meta` and `--write-doc-meta`) merge mode.
pub(crate) use_rustdoc_cci_doc_meta_merge: bool,
}

mod directives {
Expand Down Expand Up @@ -262,6 +264,7 @@ mod directives {
pub(crate) const MINICORE_COMPILE_FLAGS: &str = "minicore-compile-flags";
pub(crate) const DISABLE_GDB_PRETTY_PRINTERS: &str = "disable-gdb-pretty-printers";
pub(crate) const COMPARE_OUTPUT_BY_LINES: &str = "compare-output-by-lines";
pub(crate) const USE_RUSTDOC_CCI_DOC_META_MERGE: &str = "use-rustdoc-cci-doc-meta-merge";
}

impl TestProps {
Expand Down Expand Up @@ -319,6 +322,7 @@ impl TestProps {
dont_require_annotations: Default::default(),
disable_gdb_pretty_printers: false,
compare_output_by_lines: false,
use_rustdoc_cci_doc_meta_merge: false,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directives/directive_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"unset-rustc-env",
// Used by the tidy check `unknown_revision`.
"unused-revision-names",
"use-rustdoc-cci-doc-meta-merge",
// tidy-alphabetical-end
];

Expand Down
7 changes: 7 additions & 0 deletions src/tools/compiletest/src/directives/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,13 @@ fn make_directive_handlers_map() -> HashMap<&'static str, Handler> {
&mut props.compare_output_by_lines,
);
}),
handler(USE_RUSTDOC_CCI_DOC_META_MERGE, |config, ln, props| {
config.set_name_directive(
ln,
USE_RUSTDOC_CCI_DOC_META_MERGE,
&mut props.use_rustdoc_cci_doc_meta_merge,
);
}),
];

handlers
Expand Down
37 changes: 34 additions & 3 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,14 +1047,21 @@ impl<'test> TestCx<'test> {
.args(&self.props.doc_flags);

match kind {
DocKind::Html => {}
DocKind::Html => {
if self.props.use_rustdoc_cci_doc_meta_merge {
rustdoc.arg("--write-doc-meta-dir").arg(out_dir.as_ref().join("doc.meta"));
}
}
DocKind::Json => {
rustdoc.arg("--output-format").arg("json");
}
}

// Both JSON output and `--disable-minification` are unstable rustdoc options.
if matches!(kind, DocKind::Json) || self.config.disable_minification {
if matches!(kind, DocKind::Json)
|| self.config.disable_minification
|| self.props.use_rustdoc_cci_doc_meta_merge
{
rustdoc.arg("-Zunstable-options");
}
if self.config.disable_minification {
Expand All @@ -1065,7 +1072,31 @@ impl<'test> TestCx<'test> {
rustdoc.arg(format!("-Clinker={}", linker));
}

self.compose_and_run_compiler(rustdoc, None)
let docres = self.compose_and_run_compiler(rustdoc, None);
if !docres.status.success() {
return docres;
}
if kind == DocKind::Html && self.props.use_rustdoc_cci_doc_meta_merge {
let mut rustdoc_merge = Command::new(rustdoc_path);
let current_dir = self.output_base_dir();
rustdoc_merge.current_dir(current_dir);
rustdoc_merge
.arg("-o")
.arg(out_dir.as_ref())
.args(&self.props.compile_flags)
.args(&self.props.doc_flags)
.arg("--read-doc-meta-dir")
.arg(out_dir.as_ref().join("doc.meta"))
.arg("-Zunstable-options");
if self.config.disable_minification {
rustdoc_merge.arg("--disable-minification");
}
let docmerge = self.compose_and_run_compiler(rustdoc_merge, None);
if !docmerge.status.success() {
return docmerge;
}
}
docres
}

fn exec_compiled_test(&self) -> ProcRes {
Expand Down
17 changes: 17 additions & 0 deletions tests/rustdoc-js-std/pathbuf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// The PathBuf type is defined in std,
// but used in proc_macro. This means both crates'
// search indexes contain TypeData for it,
// but only std defines EntryData.
// This test case ensures we can merge them.
//
// https://github.com/rust-lang/rust/issues/162334


const EXPECTED = [
Comment thread
GuillaumeGomez marked this conversation as resolved.
{
query: 'PathBuf',
others: [
{ 'path': 'std::path', 'name': 'PathBuf' },
],
},
];
15 changes: 15 additions & 0 deletions tests/rustdoc-js/auxiliary/upstream-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ use-rustdoc-cci-doc-meta-merge

/// <https://github.com/rust-lang/rust/issues/162334>
pub struct FooBar;

/// Test case for overlapping struct and function name
#[allow(nonstandard_style)]
pub struct overlapping_name {
_inner: (),
}

/// Test case for overlapping function and struct name
pub fn overlapping_name() -> FooBar {
FooBar
}
Loading
Loading