From 8f5a308d0b087cb405ad6467acf1c312f93a7439 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 27 Dec 2021 19:37:15 -0800 Subject: [PATCH 1/5] rustdoc: Also index `impl Trait`s and raw pointers `dyn Trait`s and references are indexed, so these should be as well. --- src/librustdoc/html/render/search_index.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 0fbe090f2190..0f7bcdcb7f1c 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -215,17 +215,24 @@ fn get_index_type_name(clean_type: &clean::Type) -> Option { let path = &bounds[0].trait_; Some(path.segments.last().unwrap().name) } + clean::ImplTrait(ref bounds) => { + let first_trait = bounds.iter().find_map(|b| match b { + clean::GenericBound::TraitBound(poly_trait, _) => Some(&poly_trait.trait_), + clean::GenericBound::Outlives(_) => None, + }); + first_trait.map(|t| t.segments.last().unwrap().name) + } clean::Generic(s) => Some(s), clean::Primitive(ref p) => Some(p.as_sym()), - clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_), + clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => { + get_index_type_name(type_) + } clean::BareFunction(_) | clean::Tuple(_) | clean::Slice(_) | clean::Array(_, _) - | clean::RawPointer(_, _) | clean::QPath { .. } - | clean::Infer - | clean::ImplTrait(_) => None, + | clean::Infer => None, } } From 283c71e067f9b34d6fa98bd47dea68b954ad1a7e Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 28 Dec 2021 13:51:00 -0800 Subject: [PATCH 2/5] Refactor search-index types to avoid `Option`s --- src/librustdoc/html/render/mod.rs | 34 +++++++-------------- src/librustdoc/html/render/search_index.rs | 35 ++++++++++------------ 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 3e7711181f73..65397098613a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -108,8 +108,8 @@ crate struct IndexItem { /// A type used for the search index. #[derive(Debug)] crate struct RenderType { - name: Option, - generics: Option>, + name: String, + generics: Vec, } /// Full type of functions/methods in the search index. @@ -125,19 +125,15 @@ impl Serialize for IndexItemFunctionType { S: Serializer, { // If we couldn't figure out a type, just write `null`. - let has_missing = self.inputs.iter().chain(self.output.iter()).any(|i| i.ty.name.is_none()); - if has_missing { - serializer.serialize_none() - } else { - let mut seq = serializer.serialize_seq(None)?; - seq.serialize_element(&self.inputs)?; - match self.output.as_slice() { - [] => {} - [one] => seq.serialize_element(one)?, - all => seq.serialize_element(all)?, - } - seq.end() + + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.inputs)?; + match self.output.as_slice() { + [] => {} + [one] => seq.serialize_element(one)?, + all => seq.serialize_element(all)?, } + seq.end() } } @@ -147,12 +143,6 @@ crate struct TypeWithKind { kind: ItemType, } -impl From<(RenderType, ItemType)> for TypeWithKind { - fn from(x: (RenderType, ItemType)) -> TypeWithKind { - TypeWithKind { ty: x.0, kind: x.1 } - } -} - impl Serialize for TypeWithKind { fn serialize(&self, serializer: S) -> Result where @@ -161,9 +151,7 @@ impl Serialize for TypeWithKind { let mut seq = serializer.serialize_seq(None)?; seq.serialize_element(&self.ty.name)?; seq.serialize_element(&self.kind)?; - if let Some(generics) = &self.ty.generics { - seq.serialize_element(generics)?; - } + seq.serialize_element(&self.ty.generics)?; seq.end() } } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 0f7bcdcb7f1c..279624be7a86 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -185,24 +185,19 @@ crate fn get_function_type_for_search<'tcx>( item: &clean::Item, tcx: TyCtxt<'tcx>, ) -> Option { - let (mut inputs, mut output) = match *item.kind { + let (inputs, output) = match *item.kind { clean::FunctionItem(ref f) => get_fn_inputs_and_outputs(f, tcx), clean::MethodItem(ref m, _) => get_fn_inputs_and_outputs(m, tcx), clean::TyMethodItem(ref m) => get_fn_inputs_and_outputs(m, tcx), _ => return None, }; - inputs.retain(|a| a.ty.name.is_some()); - output.retain(|a| a.ty.name.is_some()); - Some(IndexItemFunctionType { inputs, output }) } -fn get_index_type(clean_type: &clean::Type, generics: Vec) -> RenderType { - RenderType { - name: get_index_type_name(clean_type).map(|s| s.as_str().to_ascii_lowercase()), - generics: if generics.is_empty() { None } else { Some(generics) }, - } +fn get_index_type(clean_type: &clean::Type, generics: Vec) -> Option { + get_index_type_name(clean_type) + .map(|s| RenderType { name: s.as_str().to_ascii_lowercase(), generics }) } fn get_index_type_name(clean_type: &clean::Type) -> Option { @@ -306,19 +301,17 @@ fn add_generics_and_bounds_as_types<'tcx>( return; } } - let mut index_ty = get_index_type(&ty, generics); - if index_ty.name.as_ref().map(|s| s.is_empty()).unwrap_or(true) { - return; - } + let Some(mut index_ty) = get_index_type(&ty, generics) + else { return }; if is_full_generic { // We remove the name of the full generic because we have no use for it. - index_ty.name = Some(String::new()); - res.push(TypeWithKind::from((index_ty, ItemType::Generic))); + index_ty.name = String::new(); + res.push(TypeWithKind { ty: index_ty, kind: ItemType::Generic }); } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { - res.push(TypeWithKind::from((index_ty, kind))); + res.push(TypeWithKind { ty: index_ty, kind }); } else if ty.is_primitive() { // This is a primitive, let's store it as such. - res.push(TypeWithKind::from((index_ty, ItemType::Primitive))); + res.push(TypeWithKind { ty: index_ty, kind: ItemType::Primitive }); } } @@ -416,7 +409,9 @@ fn get_fn_inputs_and_outputs<'tcx>( } else { if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { - all_types.push(TypeWithKind::from((get_index_type(&arg.type_, vec![]), kind))); + if let Some(ty) = get_index_type(&arg.type_, vec![]) { + all_types.push(TypeWithKind { ty, kind }); + } } } } @@ -429,7 +424,9 @@ fn get_fn_inputs_and_outputs<'tcx>( if let Some(kind) = return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { - ret_types.push(TypeWithKind::from((get_index_type(return_type, vec![]), kind))); + if let Some(ty) = get_index_type(return_type, vec![]) { + ret_types.push(TypeWithKind { ty, kind }); + } } } } From f27ed726ba150a49f03ddde72cc8cf834968608f Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 3 Jan 2022 19:27:38 -0800 Subject: [PATCH 3/5] search-index: Yield all trait bounds, not just the first --- src/librustdoc/html/render/mod.rs | 4 +- src/librustdoc/html/render/search_index.rs | 67 ++++++++++++---------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 65397098613a..53fe2afd4348 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -106,7 +106,7 @@ crate struct IndexItem { } /// A type used for the search index. -#[derive(Debug)] +#[derive(Debug, Clone)] crate struct RenderType { name: String, generics: Vec, @@ -137,7 +137,7 @@ impl Serialize for IndexItemFunctionType { } } -#[derive(Debug)] +#[derive(Debug, Clone)] crate struct TypeWithKind { ty: RenderType, kind: ItemType, diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 279624be7a86..057c4e1b0a38 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use serde::ser::{Serialize, SerializeStruct, Serializer}; +use smallvec::{smallvec, SmallVec}; use crate::clean; use crate::clean::types::{FnRetTy, Function, GenericBound, Generics, Type, WherePredicate}; @@ -195,39 +196,42 @@ crate fn get_function_type_for_search<'tcx>( Some(IndexItemFunctionType { inputs, output }) } -fn get_index_type(clean_type: &clean::Type, generics: Vec) -> Option { - get_index_type_name(clean_type) - .map(|s| RenderType { name: s.as_str().to_ascii_lowercase(), generics }) +fn get_index_types(clean_type: &clean::Type, generics: Vec) -> Vec { + get_index_type_names(clean_type) + .iter() + .map(|s| RenderType { name: s.as_str().to_ascii_lowercase(), generics: generics.clone() }) + .collect() } -fn get_index_type_name(clean_type: &clean::Type) -> Option { +fn get_index_type_names(clean_type: &clean::Type) -> SmallVec<[Symbol; 2]> { match *clean_type { clean::Type::Path { ref path, .. } => { let path_segment = path.segments.last().unwrap(); - Some(path_segment.name) + smallvec![path_segment.name] } - clean::DynTrait(ref bounds, _) => { - let path = &bounds[0].trait_; - Some(path.segments.last().unwrap().name) + clean::DynTrait(ref traits, _) => { + traits.iter().map(|t| t.trait_.segments.last().unwrap().name).collect() } - clean::ImplTrait(ref bounds) => { - let first_trait = bounds.iter().find_map(|b| match b { - clean::GenericBound::TraitBound(poly_trait, _) => Some(&poly_trait.trait_), + clean::ImplTrait(ref bounds) => bounds + .iter() + .filter_map(|b| match b { + clean::GenericBound::TraitBound(poly_trait, _) => { + Some(poly_trait.trait_.segments.last().unwrap().name) + } clean::GenericBound::Outlives(_) => None, - }); - first_trait.map(|t| t.segments.last().unwrap().name) - } - clean::Generic(s) => Some(s), - clean::Primitive(ref p) => Some(p.as_sym()), + }) + .collect(), + clean::Generic(s) => smallvec![s], + clean::Primitive(ref p) => smallvec![p.as_sym()], clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => { - get_index_type_name(type_) + get_index_type_names(type_) } clean::BareFunction(_) | clean::Tuple(_) | clean::Slice(_) | clean::Array(_, _) | clean::QPath { .. } - | clean::Infer => None, + | clean::Infer => smallvec![], } } @@ -301,17 +305,18 @@ fn add_generics_and_bounds_as_types<'tcx>( return; } } - let Some(mut index_ty) = get_index_type(&ty, generics) - else { return }; - if is_full_generic { - // We remove the name of the full generic because we have no use for it. - index_ty.name = String::new(); - res.push(TypeWithKind { ty: index_ty, kind: ItemType::Generic }); - } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { - res.push(TypeWithKind { ty: index_ty, kind }); - } else if ty.is_primitive() { - // This is a primitive, let's store it as such. - res.push(TypeWithKind { ty: index_ty, kind: ItemType::Primitive }); + for mut index_ty in get_index_types(&ty, generics) { + if is_full_generic { + // We remove the name of the full generic because we have no use for it. + index_ty.name = String::new(); + res.push(TypeWithKind { ty: index_ty, kind: ItemType::Generic }); + } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) + { + res.push(TypeWithKind { ty: index_ty, kind }); + } else if ty.is_primitive() { + // This is a primitive, let's store it as such. + res.push(TypeWithKind { ty: index_ty, kind: ItemType::Primitive }); + } } } @@ -409,7 +414,7 @@ fn get_fn_inputs_and_outputs<'tcx>( } else { if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { - if let Some(ty) = get_index_type(&arg.type_, vec![]) { + for ty in get_index_types(&arg.type_, vec![]) { all_types.push(TypeWithKind { ty, kind }); } } @@ -424,7 +429,7 @@ fn get_fn_inputs_and_outputs<'tcx>( if let Some(kind) = return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { - if let Some(ty) = get_index_type(return_type, vec![]) { + for ty in get_index_types(return_type, vec![]) { ret_types.push(TypeWithKind { ty, kind }); } } From 1186c15c6196b774c996cf1e16ba535ab90fded9 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 3 Jan 2022 19:39:24 -0800 Subject: [PATCH 4/5] Make some `clone`s explicit --- src/librustdoc/clean/auto_trait.rs | 1 + src/librustdoc/clean/types.rs | 8 ++++---- src/librustdoc/html/render/search_index.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 09692d27e8fb..d083ac9e93c9 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -502,6 +502,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { has_sized.insert(ty.clone()); } else if !b .get_trait_path() + .cloned() .and_then(|trait_| { ty_to_traits .get(&ty) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2b1a1d4a600d..a5b9f2ea20de 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1178,16 +1178,16 @@ impl GenericBound { false } - crate fn get_poly_trait(&self) -> Option { + crate fn get_poly_trait(&self) -> Option<&PolyTrait> { if let GenericBound::TraitBound(ref p, _) = *self { - return Some(p.clone()); + return Some(p); } None } - crate fn get_trait_path(&self) -> Option { + crate fn get_trait_path(&self) -> Option<&Path> { if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { - Some(trait_.clone()) + Some(trait_) } else { None } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 057c4e1b0a38..81021ff9ade2 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -363,7 +363,7 @@ fn add_generics_and_bounds_as_types<'tcx>( let mut ty_generics = Vec::new(); for bound in bound.get_bounds().unwrap_or(&[]) { if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; + let ty = Type::Path { path: path.clone() }; add_generics_and_bounds_as_types( generics, &ty, From e7222b9b36d6d928fcda723b38d6ae86a7539f2b Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 3 Jan 2022 19:43:57 -0800 Subject: [PATCH 5/5] Clean up some code to make it simpler --- src/librustdoc/clean/types.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a5b9f2ea20de..d682ab7e5991 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -292,19 +292,16 @@ impl ExternalCrate { let as_primitive = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); - let mut prim = None; for attr in attrs.lists(sym::doc) { if let Some(v) = attr.value_str() { if attr.has_name(sym::primitive) { - prim = PrimitiveType::from_symbol(v); - if prim.is_some() { - break; + if let Some(prim) = PrimitiveType::from_symbol(v) { + return Some((def_id, prim)); } // FIXME: should warn on unknown primitives? } } } - return prim.map(|p| (def_id, p)); } None };