let mut crate_items = Vec::with_capacity(cache.search_index.len());
let mut crate_paths = vec![];
- // For now we don't get the primitive types in the search index.
- let empty_cache = Cache::default();
// Attach all orphan items to the type's definition if the type
// has since been learned.
for &(did, ref item) in &cache.orphan_impl_items {
desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)),
parent: Some(did),
parent_idx: None,
- search_type: get_index_search_type(&item, cache),
+ search_type: get_index_search_type(&item, cache, tcx),
});
for alias in item.attrs.get_doc_aliases() {
cache
if r.is_empty() { None } else { Some(r) }
})
}
+
+/// The point of this function is to replace bounds with types.
+///
+/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
+/// `[Display, Option]` (we just returns the list of the types, we don't care about the
+/// wrapped types in here).
+crate fn get_real_types<'tcx>(
+ generics: &Generics,
+ arg: &Type,
+ tcx: TyCtxt<'tcx>,
+ recurse: i32,
+ cache: &Cache,
+ res: &mut FxHashSet<(Type, TypeKind)>,
+) -> usize {
+ fn insert(res: &mut FxHashSet<(Type, TypeKind)>, tcx: TyCtxt<'_>, ty: Type) -> usize {
+ if let Some(kind) = ty.def_id().map(|did| tcx.def_kind(did).into()) {
+ res.insert((ty, kind));
+ 1
+ } else if ty.is_primitive() {
+ // This is a primitive, let's store it as such.
+ res.insert((ty, TypeKind::Primitive));
+ 1
+ } else {
+ 0
+ }
+ }
+
+ if recurse >= 10 {
+ // FIXME: remove this whole recurse thing when the recursion bug is fixed
+ return 0;
+ }
+ let mut nb_added = 0;
+
+ if arg.is_full_generic() {
+ let arg_s = Symbol::intern(&arg.print(cache).to_string());
+ if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
+ WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(),
+ _ => false,
+ }) {
+ let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
+ for bound in bounds.iter() {
+ if let GenericBound::TraitBound(poly_trait, _) = bound {
+ for x in poly_trait.generic_params.iter() {
+ if !x.is_type() {
+ continue;
+ }
+ if let Some(ty) = x.get_type() {
+ let adds = get_real_types(generics, &ty, tcx, recurse + 1, cache, res);
+ nb_added += adds;
+ if adds == 0 && !ty.is_full_generic() {
+ nb_added += insert(res, tcx, ty);
+ }
+ }
+ }
+ }
+ }
+ }
+ if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
+ for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
+ if let Some(ty) = bound.get_trait_type() {
+ let adds = get_real_types(generics, &ty, tcx, recurse + 1, cache, res);
+ nb_added += adds;
+ if adds == 0 && !ty.is_full_generic() {
+ nb_added += insert(res, tcx, ty);
+ }
+ }
+ }
+ }
+ } else {
+ nb_added += insert(res, tcx, arg.clone());
+ if let Some(gens) = arg.generics() {
+ for gen in gens.iter() {
+ if gen.is_full_generic() {
+ nb_added += get_real_types(generics, gen, tcx, recurse + 1, cache, res);
+ } else {
+ nb_added += insert(res, tcx, (*gen).clone());
+ }
+ }
+ }
+ }
+ nb_added
+}
+
+/// Return the full list of types when bounds have been resolved.
+///
+/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
+/// `[u32, Display, Option]`.
+crate fn get_all_types<'tcx>(
+ generics: &Generics,
+ decl: &FnDecl,
+ tcx: TyCtxt<'tcx>,
+ cache: &Cache,
+) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) {
+ let mut all_types = FxHashSet::default();
+ for arg in decl.inputs.values.iter() {
+ if arg.type_.is_self_type() {
+ continue;
+ }
+ let mut args = FxHashSet::default();
+ get_real_types(generics, &arg.type_, tcx, 0, cache, &mut args);
+ if !args.is_empty() {
+ all_types.extend(args);
+ } else {
+ if let Some(kind) = arg.type_.def_id().map(|did| tcx.def_kind(did).into()) {
+ all_types.insert((arg.type_.clone(), kind));
+ }
+ }
+ }
+
+ let ret_types = match decl.output {
+ FnRetTy::Return(ref return_type) => {
+ let mut ret = FxHashSet::default();
+ get_real_types(generics, &return_type, tcx, 0, cache, &mut ret);
+ if ret.is_empty() {
+ if let Some(kind) = return_type.def_id().map(|did| tcx.def_kind(did).into()) {
+ ret.insert((return_type.clone(), kind));
+ }
+ }
+ ret.into_iter().collect()
+ }
+ _ => Vec::new(),
+ };
+ (all_types.into_iter().collect(), ret_types)
+}