Skip to content

Commit dab9e21

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 d895ceb + 85b6723 commit dab9e21

File tree

9 files changed

+236
-106
lines changed

9 files changed

+236
-106
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,26 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
10761076
}
10771077
}
10781078

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

src/librustdoc/clean/types.rs

Lines changed: 7 additions & 7 deletions
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)]
@@ -1042,7 +1042,7 @@ pub enum PrimitiveType {
10421042
Never,
10431043
}
10441044

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

src/librustdoc/clean/utils.rs

Lines changed: 31 additions & 9 deletions
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

Lines changed: 61 additions & 9 deletions
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::{OutputFormat, RenderOptions};
6464
use crate::docfs::{DocFS, ErrorStorage, PathError};
6565
use crate::doctree;
@@ -303,19 +303,25 @@ impl Serialize for IndexItem {
303303

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

311-
impl Serialize for Type {
313+
impl Serialize for RenderType {
312314
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
313315
where
314316
S: Serializer,
315317
{
316318
if let Some(name) = &self.name {
317319
let mut seq = serializer.serialize_seq(None)?;
318-
seq.serialize_element(&name)?;
320+
if let Some(id) = self.idx {
321+
seq.serialize_element(&id)?;
322+
} else {
323+
seq.serialize_element(&name)?;
324+
}
319325
if let Some(generics) = &self.generics {
320326
seq.serialize_element(&generics)?;
321327
}
@@ -326,11 +332,32 @@ impl Serialize for Type {
326332
}
327333
}
328334

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

336363
impl Serialize for IndexItemFunctionType {
@@ -341,8 +368,8 @@ impl Serialize for IndexItemFunctionType {
341368
// If we couldn't figure out a type, just write `null`.
342369
let mut iter = self.inputs.iter();
343370
if match self.output {
344-
Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
345-
None => iter.any(|ref i| i.name.is_none()),
371+
Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
372+
None => iter.any(|ref i| i.ty.name.is_none()),
346373
} {
347374
serializer.serialize_none()
348375
} else {
@@ -360,6 +387,31 @@ impl Serialize for IndexItemFunctionType {
360387
}
361388
}
362389

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

src/librustdoc/html/render/cache.rs

Lines changed: 28 additions & 15 deletions
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 {
@@ -588,17 +588,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
588588
let mut lastpathid = 0usize;
589589

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

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

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

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

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

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

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

0 commit comments

Comments
 (0)