Skip to content

Commit b17a0f7

Browse files
authored
Rollup merge of rust-lang#69402 - GuillaumeGomez:extend-search, r=kinnison
Extend search I realized that when looking for "struct:String" in the rustdoc search for example, the "in arguments" and "returned" tabs were always empty. After some investigation, I realized it was because we only provided the name, and not the type, making it impossible to pass the "type filtering" check. To resolve this, I added the type alongside the name. Note for the future: we could improve this by instead only registering the path id and use the path dictionary directly. The only problem with that solution (which I already tested) is that it becomes complicated for types in other crates. It'd force us to handle both case with an id and a case with `(name, type)`. I found the current PR big enough to not want to provide it directly. However, I think this is definitely worth it to make it work this way in the future. About the two tests I added: they don't have much interest except checking that we actually have something returned in the search in the cases of a type filtering with and without literal search. I also had to update a bit the test script to add the new locally global (haha) variable I created (`NO_TYPE_FILTER`). I added this variable to make the code easier to read than just "-1". r? @kinnison cc @ollie27
2 parents e5999e1 + 6ffe9f3 commit b17a0f7

File tree

9 files changed

+236
-106
lines changed

9 files changed

+236
-106
lines changed

src/librustdoc/clean/mod.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,26 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
10781078
}
10791079
}
10801080

1081+
impl Clean<TypeKind> for hir::def::DefKind {
1082+
fn clean(&self, _: &DocContext<'_>) -> TypeKind {
1083+
match *self {
1084+
hir::def::DefKind::Mod => TypeKind::Module,
1085+
hir::def::DefKind::Struct => TypeKind::Struct,
1086+
hir::def::DefKind::Union => TypeKind::Union,
1087+
hir::def::DefKind::Enum => TypeKind::Enum,
1088+
hir::def::DefKind::Trait => TypeKind::Trait,
1089+
hir::def::DefKind::TyAlias => TypeKind::Typedef,
1090+
hir::def::DefKind::ForeignTy => TypeKind::Foreign,
1091+
hir::def::DefKind::TraitAlias => TypeKind::TraitAlias,
1092+
hir::def::DefKind::Fn => TypeKind::Function,
1093+
hir::def::DefKind::Const => TypeKind::Const,
1094+
hir::def::DefKind::Static => TypeKind::Static,
1095+
hir::def::DefKind::Macro(_) => TypeKind::Macro,
1096+
_ => TypeKind::Foreign,
1097+
}
1098+
}
1099+
}
1100+
10811101
impl Clean<Item> for hir::TraitItem<'_> {
10821102
fn clean(&self, cx: &DocContext<'_>) -> Item {
10831103
let inner = match self.kind {

src/librustdoc/clean/types.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -836,26 +836,26 @@ pub struct Method {
836836
pub decl: FnDecl,
837837
pub header: hir::FnHeader,
838838
pub defaultness: Option<hir::Defaultness>,
839-
pub all_types: Vec<Type>,
840-
pub ret_types: Vec<Type>,
839+
pub all_types: Vec<(Type, TypeKind)>,
840+
pub ret_types: Vec<(Type, TypeKind)>,
841841
}
842842

843843
#[derive(Clone, Debug)]
844844
pub struct TyMethod {
845845
pub header: hir::FnHeader,
846846
pub decl: FnDecl,
847847
pub generics: Generics,
848-
pub all_types: Vec<Type>,
849-
pub ret_types: Vec<Type>,
848+
pub all_types: Vec<(Type, TypeKind)>,
849+
pub ret_types: Vec<(Type, TypeKind)>,
850850
}
851851

852852
#[derive(Clone, Debug)]
853853
pub struct Function {
854854
pub decl: FnDecl,
855855
pub generics: Generics,
856856
pub header: hir::FnHeader,
857-
pub all_types: Vec<Type>,
858-
pub ret_types: Vec<Type>,
857+
pub all_types: Vec<(Type, TypeKind)>,
858+
pub ret_types: Vec<(Type, TypeKind)>,
859859
}
860860

861861
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -1043,7 +1043,7 @@ pub enum PrimitiveType {
10431043
Never,
10441044
}
10451045

1046-
#[derive(Clone, Copy, Debug)]
1046+
#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
10471047
pub enum TypeKind {
10481048
Enum,
10491049
Function,

src/librustdoc/clean/utils.rs

+31-9
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ pub fn get_real_types(
184184
arg: &Type,
185185
cx: &DocContext<'_>,
186186
recurse: i32,
187-
) -> FxHashSet<Type> {
187+
) -> FxHashSet<(Type, TypeKind)> {
188188
let arg_s = arg.print().to_string();
189189
let mut res = FxHashSet::default();
190190
if recurse >= 10 {
@@ -209,7 +209,11 @@ pub fn get_real_types(
209209
if !adds.is_empty() {
210210
res.extend(adds);
211211
} else if !ty.is_full_generic() {
212-
res.insert(ty);
212+
if let Some(did) = ty.def_id() {
213+
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
214+
res.insert((ty, kind));
215+
}
216+
}
213217
}
214218
}
215219
}
@@ -225,22 +229,32 @@ pub fn get_real_types(
225229
if !adds.is_empty() {
226230
res.extend(adds);
227231
} else if !ty.is_full_generic() {
228-
res.insert(ty.clone());
232+
if let Some(did) = ty.def_id() {
233+
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
234+
res.insert((ty.clone(), kind));
235+
}
236+
}
229237
}
230238
}
231239
}
232240
}
233241
} else {
234-
res.insert(arg.clone());
242+
if let Some(did) = arg.def_id() {
243+
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
244+
res.insert((arg.clone(), kind));
245+
}
246+
}
235247
if let Some(gens) = arg.generics() {
236248
for gen in gens.iter() {
237249
if gen.is_full_generic() {
238250
let adds = get_real_types(generics, gen, cx, recurse + 1);
239251
if !adds.is_empty() {
240252
res.extend(adds);
241253
}
242-
} else {
243-
res.insert(gen.clone());
254+
} else if let Some(did) = gen.def_id() {
255+
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
256+
res.insert((gen.clone(), kind));
257+
}
244258
}
245259
}
246260
}
@@ -256,7 +270,7 @@ pub fn get_all_types(
256270
generics: &Generics,
257271
decl: &FnDecl,
258272
cx: &DocContext<'_>,
259-
) -> (Vec<Type>, Vec<Type>) {
273+
) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) {
260274
let mut all_types = FxHashSet::default();
261275
for arg in decl.inputs.values.iter() {
262276
if arg.type_.is_self_type() {
@@ -266,15 +280,23 @@ pub fn get_all_types(
266280
if !args.is_empty() {
267281
all_types.extend(args);
268282
} else {
269-
all_types.insert(arg.type_.clone());
283+
if let Some(did) = arg.type_.def_id() {
284+
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
285+
all_types.insert((arg.type_.clone(), kind));
286+
}
287+
}
270288
}
271289
}
272290

273291
let ret_types = match decl.output {
274292
FnRetTy::Return(ref return_type) => {
275293
let mut ret = get_real_types(generics, &return_type, cx, 0);
276294
if ret.is_empty() {
277-
ret.insert(return_type.clone());
295+
if let Some(did) = return_type.def_id() {
296+
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
297+
ret.insert((return_type.clone(), kind));
298+
}
299+
}
278300
}
279301
ret.into_iter().collect()
280302
}

src/librustdoc/html/render.rs

+61-9
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use rustc_span::symbol::{sym, Symbol};
5959
use serde::ser::SerializeSeq;
6060
use serde::{Serialize, Serializer};
6161

62-
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy};
62+
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
6363
use crate::config::RenderOptions;
6464
use crate::docfs::{DocFS, ErrorStorage, PathError};
6565
use crate::doctree;
@@ -302,19 +302,25 @@ impl Serialize for IndexItem {
302302

303303
/// A type used for the search index.
304304
#[derive(Debug)]
305-
struct Type {
305+
struct RenderType {
306+
ty: Option<DefId>,
307+
idx: Option<usize>,
306308
name: Option<String>,
307-
generics: Option<Vec<String>>,
309+
generics: Option<Vec<Generic>>,
308310
}
309311

310-
impl Serialize for Type {
312+
impl Serialize for RenderType {
311313
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
312314
where
313315
S: Serializer,
314316
{
315317
if let Some(name) = &self.name {
316318
let mut seq = serializer.serialize_seq(None)?;
317-
seq.serialize_element(&name)?;
319+
if let Some(id) = self.idx {
320+
seq.serialize_element(&id)?;
321+
} else {
322+
seq.serialize_element(&name)?;
323+
}
318324
if let Some(generics) = &self.generics {
319325
seq.serialize_element(&generics)?;
320326
}
@@ -325,11 +331,32 @@ impl Serialize for Type {
325331
}
326332
}
327333

334+
/// A type used for the search index.
335+
#[derive(Debug)]
336+
struct Generic {
337+
name: String,
338+
defid: Option<DefId>,
339+
idx: Option<usize>,
340+
}
341+
342+
impl Serialize for Generic {
343+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
344+
where
345+
S: Serializer,
346+
{
347+
if let Some(id) = self.idx {
348+
serializer.serialize_some(&id)
349+
} else {
350+
serializer.serialize_some(&self.name)
351+
}
352+
}
353+
}
354+
328355
/// Full type of functions/methods in the search index.
329356
#[derive(Debug)]
330357
struct IndexItemFunctionType {
331-
inputs: Vec<Type>,
332-
output: Option<Vec<Type>>,
358+
inputs: Vec<TypeWithKind>,
359+
output: Option<Vec<TypeWithKind>>,
333360
}
334361

335362
impl Serialize for IndexItemFunctionType {
@@ -340,8 +367,8 @@ impl Serialize for IndexItemFunctionType {
340367
// If we couldn't figure out a type, just write `null`.
341368
let mut iter = self.inputs.iter();
342369
if match self.output {
343-
Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
344-
None => iter.any(|ref i| i.name.is_none()),
370+
Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
371+
None => iter.any(|ref i| i.ty.name.is_none()),
345372
} {
346373
serializer.serialize_none()
347374
} else {
@@ -359,6 +386,31 @@ impl Serialize for IndexItemFunctionType {
359386
}
360387
}
361388

389+
#[derive(Debug)]
390+
pub struct TypeWithKind {
391+
ty: RenderType,
392+
kind: TypeKind,
393+
}
394+
395+
impl From<(RenderType, TypeKind)> for TypeWithKind {
396+
fn from(x: (RenderType, TypeKind)) -> TypeWithKind {
397+
TypeWithKind { ty: x.0, kind: x.1 }
398+
}
399+
}
400+
401+
impl Serialize for TypeWithKind {
402+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
403+
where
404+
S: Serializer,
405+
{
406+
let mut seq = serializer.serialize_seq(None)?;
407+
seq.serialize_element(&self.ty.name)?;
408+
let x: ItemType = self.kind.into();
409+
seq.serialize_element(&x)?;
410+
seq.end()
411+
}
412+
}
413+
362414
thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
363415
thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
364416

src/librustdoc/html/render/cache.rs

+28-15
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::path::{Path, PathBuf};
1212
use serde::Serialize;
1313

1414
use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType};
15-
use super::{RenderInfo, Type};
15+
use super::{Generic, RenderInfo, RenderType, TypeWithKind};
1616

1717
/// Indicates where an external crate can be found.
1818
pub enum ExternalLocation {
@@ -587,17 +587,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
587587
let mut lastpathid = 0usize;
588588

589589
for item in search_index {
590-
item.parent_idx = item.parent.map(|defid| {
590+
item.parent_idx = item.parent.and_then(|defid| {
591591
if defid_to_pathid.contains_key(&defid) {
592-
*defid_to_pathid.get(&defid).expect("no pathid")
592+
defid_to_pathid.get(&defid).map(|x| *x)
593593
} else {
594594
let pathid = lastpathid;
595595
defid_to_pathid.insert(defid, pathid);
596596
lastpathid += 1;
597597

598-
let &(ref fqp, short) = paths.get(&defid).unwrap();
599-
crate_paths.push((short, fqp.last().unwrap().clone()));
600-
pathid
598+
if let Some(&(ref fqp, short)) = paths.get(&defid) {
599+
crate_paths.push((short, fqp.last().unwrap().clone()));
600+
Some(pathid)
601+
} else {
602+
None
603+
}
601604
}
602605
});
603606

@@ -646,20 +649,25 @@ fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
646649
_ => return None,
647650
};
648651

649-
let inputs =
650-
all_types.iter().map(|arg| get_index_type(&arg)).filter(|a| a.name.is_some()).collect();
652+
let inputs = all_types
653+
.iter()
654+
.map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
655+
.filter(|a| a.ty.name.is_some())
656+
.collect();
651657
let output = ret_types
652658
.iter()
653-
.map(|arg| get_index_type(&arg))
654-
.filter(|a| a.name.is_some())
659+
.map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
660+
.filter(|a| a.ty.name.is_some())
655661
.collect::<Vec<_>>();
656662
let output = if output.is_empty() { None } else { Some(output) };
657663

658664
Some(IndexItemFunctionType { inputs, output })
659665
}
660666

661-
fn get_index_type(clean_type: &clean::Type) -> Type {
662-
let t = Type {
667+
fn get_index_type(clean_type: &clean::Type) -> RenderType {
668+
let t = RenderType {
669+
ty: clean_type.def_id(),
670+
idx: None,
663671
name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()),
664672
generics: get_generics(clean_type),
665673
};
@@ -684,12 +692,17 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
684692
}
685693
}
686694

687-
fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
695+
fn get_generics(clean_type: &clean::Type) -> Option<Vec<Generic>> {
688696
clean_type.generics().and_then(|types| {
689697
let r = types
690698
.iter()
691-
.filter_map(|t| get_index_type_name(t, false))
692-
.map(|s| s.to_ascii_lowercase())
699+
.filter_map(|t| {
700+
if let Some(name) = get_index_type_name(t, false) {
701+
Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None })
702+
} else {
703+
None
704+
}
705+
})
693706
.collect::<Vec<_>>();
694707
if r.is_empty() { None } else { Some(r) }
695708
})

0 commit comments

Comments
 (0)