From e161fa1a6b3752da0a9279298eedf5b84a5fe49f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 2 Sep 2023 23:04:37 +0200 Subject: [PATCH] Correctly handle paths from foreign items --- src/librustdoc/html/render/search_index.rs | 57 +++++++++++++++++----- tests/rustdoc-js/full-path-function.js | 18 +++++++ tests/rustdoc-js/full-path-function.rs | 1 + 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 2bbfb64ecb538..145c7d18dd013 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1,7 +1,7 @@ use std::collections::hash_map::Entry; use std::collections::BTreeMap; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer}; @@ -246,6 +246,11 @@ pub(crate) fn build_index<'tcx>( where S: Serializer, { + let mut extra_paths = FxHashMap::default(); + // We need to keep the order of insertion, hence why we use an `IndexMap`. Then we will + // insert these "extra paths" (which are paths of items from external crates) into the + // `full_paths` list at the end. + let mut revert_extra_paths = FxIndexMap::default(); let mut mod_paths = FxHashMap::default(); for (index, item) in self.items.iter().enumerate() { if item.path.is_empty() { @@ -253,17 +258,43 @@ pub(crate) fn build_index<'tcx>( } mod_paths.insert(&item.path, index); } - let paths = self - .paths - .iter() - .map(|(ty, path)| { - if path.len() < 2 { - return Paths { ty: *ty, name: path[0], path: None }; + let mut paths = Vec::with_capacity(self.paths.len()); + for (ty, path) in &self.paths { + if path.len() < 2 { + paths.push(Paths { ty: *ty, name: path[0], path: None }); + continue; + } + let full_path = join_with_double_colon(&path[..path.len() - 1]); + if let Some(index) = mod_paths.get(&full_path) { + paths.push(Paths { ty: *ty, name: *path.last().unwrap(), path: Some(*index) }); + continue; + } + // It means it comes from an external crate so the item and its path will be + // stored into another array. + // + // `index` is put after the last `mod_paths` + let index = extra_paths.len() + self.items.len(); + if !revert_extra_paths.contains_key(&index) { + revert_extra_paths.insert(index, full_path.clone()); + } + match extra_paths.entry(full_path) { + Entry::Occupied(entry) => { + paths.push(Paths { + ty: *ty, + name: *path.last().unwrap(), + path: Some(*entry.get()), + }); } - let index = mod_paths.get(&join_with_double_colon(&path[..path.len() - 1])); - Paths { ty: *ty, name: *path.last().unwrap(), path: index.copied() } - }) - .collect::>(); + Entry::Vacant(entry) => { + entry.insert(index); + paths.push(Paths { + ty: *ty, + name: *path.last().unwrap(), + path: Some(index), + }); + } + } + } let mut names = Vec::with_capacity(self.items.len()); let mut types = String::with_capacity(self.items.len()); @@ -322,6 +353,10 @@ pub(crate) fn build_index<'tcx>( } } + for (index, path) in &revert_extra_paths { + full_paths.push((*index, path)); + } + let has_aliases = !self.aliases.is_empty(); let mut crate_data = serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?; diff --git a/tests/rustdoc-js/full-path-function.js b/tests/rustdoc-js/full-path-function.js index 9d3c3a4506c40..48be51b156fde 100644 --- a/tests/rustdoc-js/full-path-function.js +++ b/tests/rustdoc-js/full-path-function.js @@ -22,4 +22,22 @@ const EXPECTED = [ { 'path': 'full_path_function::b::Sac', 'name': 'bar2' }, ], }, + { + 'query': 'string::string -> u32', + 'others': [ + { 'path': 'full_path_function::b::Sac', 'name': 'string' }, + ], + }, + { + 'query': 'alloc::string::string -> u32', + 'others': [ + { 'path': 'full_path_function::b::Sac', 'name': 'string' }, + ], + }, + { + 'query': 'alloc::string -> u32', + 'others': [ + { 'path': 'full_path_function::b::Sac', 'name': 'string' }, + ], + }, ]; diff --git a/tests/rustdoc-js/full-path-function.rs b/tests/rustdoc-js/full-path-function.rs index c1ec1e1731b13..8dcc3f2b69d84 100644 --- a/tests/rustdoc-js/full-path-function.rs +++ b/tests/rustdoc-js/full-path-function.rs @@ -12,5 +12,6 @@ pub mod b { pub fn len(&self) -> usize { 0 } pub fn bar(&self, w: u32) -> usize { 0 } pub fn bar2(&self, w: u32) -> u32 { 0 } + pub fn string(w: String) -> u32 { 0 } } }