Skip to content

Commit e161fa1

Browse files
Correctly handle paths from foreign items
1 parent 36fa557 commit e161fa1

File tree

3 files changed

+65
-11
lines changed

3 files changed

+65
-11
lines changed

src/librustdoc/html/render/search_index.rs

+46-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::hash_map::Entry;
22
use std::collections::BTreeMap;
33

4-
use rustc_data_structures::fx::FxHashMap;
4+
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
55
use rustc_middle::ty::TyCtxt;
66
use rustc_span::symbol::Symbol;
77
use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer};
@@ -246,24 +246,55 @@ pub(crate) fn build_index<'tcx>(
246246
where
247247
S: Serializer,
248248
{
249+
let mut extra_paths = FxHashMap::default();
250+
// We need to keep the order of insertion, hence why we use an `IndexMap`. Then we will
251+
// insert these "extra paths" (which are paths of items from external crates) into the
252+
// `full_paths` list at the end.
253+
let mut revert_extra_paths = FxIndexMap::default();
249254
let mut mod_paths = FxHashMap::default();
250255
for (index, item) in self.items.iter().enumerate() {
251256
if item.path.is_empty() {
252257
continue;
253258
}
254259
mod_paths.insert(&item.path, index);
255260
}
256-
let paths = self
257-
.paths
258-
.iter()
259-
.map(|(ty, path)| {
260-
if path.len() < 2 {
261-
return Paths { ty: *ty, name: path[0], path: None };
261+
let mut paths = Vec::with_capacity(self.paths.len());
262+
for (ty, path) in &self.paths {
263+
if path.len() < 2 {
264+
paths.push(Paths { ty: *ty, name: path[0], path: None });
265+
continue;
266+
}
267+
let full_path = join_with_double_colon(&path[..path.len() - 1]);
268+
if let Some(index) = mod_paths.get(&full_path) {
269+
paths.push(Paths { ty: *ty, name: *path.last().unwrap(), path: Some(*index) });
270+
continue;
271+
}
272+
// It means it comes from an external crate so the item and its path will be
273+
// stored into another array.
274+
//
275+
// `index` is put after the last `mod_paths`
276+
let index = extra_paths.len() + self.items.len();
277+
if !revert_extra_paths.contains_key(&index) {
278+
revert_extra_paths.insert(index, full_path.clone());
279+
}
280+
match extra_paths.entry(full_path) {
281+
Entry::Occupied(entry) => {
282+
paths.push(Paths {
283+
ty: *ty,
284+
name: *path.last().unwrap(),
285+
path: Some(*entry.get()),
286+
});
262287
}
263-
let index = mod_paths.get(&join_with_double_colon(&path[..path.len() - 1]));
264-
Paths { ty: *ty, name: *path.last().unwrap(), path: index.copied() }
265-
})
266-
.collect::<Vec<_>>();
288+
Entry::Vacant(entry) => {
289+
entry.insert(index);
290+
paths.push(Paths {
291+
ty: *ty,
292+
name: *path.last().unwrap(),
293+
path: Some(index),
294+
});
295+
}
296+
}
297+
}
267298

268299
let mut names = Vec::with_capacity(self.items.len());
269300
let mut types = String::with_capacity(self.items.len());
@@ -322,6 +353,10 @@ pub(crate) fn build_index<'tcx>(
322353
}
323354
}
324355

356+
for (index, path) in &revert_extra_paths {
357+
full_paths.push((*index, path));
358+
}
359+
325360
let has_aliases = !self.aliases.is_empty();
326361
let mut crate_data =
327362
serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?;

tests/rustdoc-js/full-path-function.js

+18
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,22 @@ const EXPECTED = [
2222
{ 'path': 'full_path_function::b::Sac', 'name': 'bar2' },
2323
],
2424
},
25+
{
26+
'query': 'string::string -> u32',
27+
'others': [
28+
{ 'path': 'full_path_function::b::Sac', 'name': 'string' },
29+
],
30+
},
31+
{
32+
'query': 'alloc::string::string -> u32',
33+
'others': [
34+
{ 'path': 'full_path_function::b::Sac', 'name': 'string' },
35+
],
36+
},
37+
{
38+
'query': 'alloc::string -> u32',
39+
'others': [
40+
{ 'path': 'full_path_function::b::Sac', 'name': 'string' },
41+
],
42+
},
2543
];

tests/rustdoc-js/full-path-function.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ pub mod b {
1212
pub fn len(&self) -> usize { 0 }
1313
pub fn bar(&self, w: u32) -> usize { 0 }
1414
pub fn bar2(&self, w: u32) -> u32 { 0 }
15+
pub fn string(w: String) -> u32 { 0 }
1516
}
1617
}

0 commit comments

Comments
 (0)