-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rustdoc: Start cleaning up search index generation #92340
Changes from all commits
60a1abe
e19593f
2b801dc
bd6692c
afb77a9
5c8e8e5
7d1ec64
908a9d4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,22 +7,12 @@ use rustc_span::symbol::Symbol; | |
use serde::ser::{Serialize, SerializeStruct, Serializer}; | ||
|
||
use crate::clean; | ||
use crate::clean::types::{FnDecl, FnRetTy, GenericBound, Generics, Type, WherePredicate}; | ||
use crate::clean::types::{FnRetTy, Function, GenericBound, Generics, Type, WherePredicate}; | ||
use crate::formats::cache::Cache; | ||
use crate::formats::item_type::ItemType; | ||
use crate::html::markdown::short_markdown_summary; | ||
use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind}; | ||
|
||
/// Indicates where an external crate can be found. | ||
crate enum ExternalLocation { | ||
/// Remote URL root of the external crate | ||
Remote(String), | ||
/// This external crate can be found in the local doc/ folder | ||
Local, | ||
/// The external crate could not be found. | ||
Unknown, | ||
} | ||
|
||
/// Builds the search index from the collected metadata | ||
crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>) -> String { | ||
let mut defid_to_pathid = FxHashMap::default(); | ||
|
@@ -42,7 +32,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< | |
desc, | ||
parent: Some(did), | ||
parent_idx: None, | ||
search_type: get_index_search_type(item, tcx, cache), | ||
search_type: get_function_type_for_search(item, tcx), | ||
aliases: item.attrs.get_doc_aliases(), | ||
}); | ||
} | ||
|
@@ -191,15 +181,14 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< | |
) | ||
} | ||
|
||
crate fn get_index_search_type<'tcx>( | ||
crate fn get_function_type_for_search<'tcx>( | ||
item: &clean::Item, | ||
tcx: TyCtxt<'tcx>, | ||
cache: &Cache, | ||
) -> Option<IndexItemFunctionType> { | ||
let (mut inputs, mut output) = match *item.kind { | ||
clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx, cache), | ||
clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx, cache), | ||
clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx, cache), | ||
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, | ||
}; | ||
|
||
|
@@ -211,12 +200,12 @@ crate fn get_index_search_type<'tcx>( | |
|
||
fn get_index_type(clean_type: &clean::Type, generics: Vec<TypeWithKind>) -> RenderType { | ||
RenderType { | ||
name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), | ||
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_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> { | ||
fn get_index_type_name(clean_type: &clean::Type) -> Option<Symbol> { | ||
match *clean_type { | ||
clean::Type::Path { ref path, .. } => { | ||
let path_segment = path.segments.last().unwrap(); | ||
|
@@ -226,11 +215,10 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option | |
let path = &bounds[0].trait_; | ||
Some(path.segments.last().unwrap().name) | ||
} | ||
clean::Generic(s) if accept_generic => Some(s), | ||
clean::Generic(s) => Some(s), | ||
clean::Primitive(ref p) => Some(p.as_sym()), | ||
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), | ||
clean::Generic(_) | ||
| clean::BareFunction(_) | ||
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_), | ||
clean::BareFunction(_) | ||
| clean::Tuple(_) | ||
| clean::Slice(_) | ||
| clean::Array(_, _) | ||
|
@@ -248,20 +236,19 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option | |
/// | ||
/// Important note: It goes through generics recursively. So if you have | ||
/// `T: Option<Result<(), ()>>`, it'll go into `Option` and then into `Result`. | ||
crate fn get_real_types<'tcx>( | ||
#[instrument(level = "trace", skip(tcx, res))] | ||
fn add_generics_and_bounds_as_types<'tcx>( | ||
generics: &Generics, | ||
arg: &Type, | ||
tcx: TyCtxt<'tcx>, | ||
recurse: usize, | ||
res: &mut Vec<TypeWithKind>, | ||
cache: &Cache, | ||
) { | ||
fn insert_ty( | ||
res: &mut Vec<TypeWithKind>, | ||
tcx: TyCtxt<'_>, | ||
ty: Type, | ||
mut generics: Vec<TypeWithKind>, | ||
_cache: &Cache, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is the right move because of: } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { We are replacing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I see what you mean, but the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I reviewed a PR doing exactly that today (but of course, can't find it again...). I'd prefer to avoid having removals/adds following but not sure it matters much since it's just about git history here... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're thinking of #92342? I'd rather remove the dead code for now – e.g., that PR may not work and end up being closed, and then the dead code will still be there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't fully agree with you but it's fine. Let's move forward then! |
||
) { | ||
let is_full_generic = ty.is_full_generic(); | ||
|
||
|
@@ -330,6 +317,7 @@ crate fn get_real_types<'tcx>( | |
|
||
if recurse >= 10 { | ||
camelid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// FIXME: remove this whole recurse thing when the recursion bug is fixed | ||
// See #59502 for the original issue. | ||
return; | ||
} | ||
|
||
|
@@ -350,32 +338,37 @@ crate fn get_real_types<'tcx>( | |
for param_def in poly_trait.generic_params.iter() { | ||
match ¶m_def.kind { | ||
clean::GenericParamDefKind::Type { default: Some(ty), .. } => { | ||
get_real_types( | ||
add_generics_and_bounds_as_types( | ||
generics, | ||
ty, | ||
tcx, | ||
recurse + 1, | ||
&mut ty_generics, | ||
cache, | ||
) | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
} | ||
insert_ty(res, tcx, arg.clone(), ty_generics, cache); | ||
insert_ty(res, tcx, arg.clone(), ty_generics); | ||
} | ||
// Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`... | ||
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { | ||
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 }; | ||
get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache); | ||
add_generics_and_bounds_as_types( | ||
generics, | ||
&ty, | ||
tcx, | ||
recurse + 1, | ||
&mut ty_generics, | ||
); | ||
} | ||
} | ||
insert_ty(res, tcx, arg.clone(), ty_generics, cache); | ||
insert_ty(res, tcx, arg.clone(), ty_generics); | ||
} | ||
} else { | ||
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're | ||
|
@@ -386,30 +379,31 @@ crate fn get_real_types<'tcx>( | |
let mut ty_generics = Vec::new(); | ||
if let Some(arg_generics) = arg.generics() { | ||
for gen in arg_generics.iter() { | ||
get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics, cache); | ||
add_generics_and_bounds_as_types(generics, gen, tcx, recurse + 1, &mut ty_generics); | ||
} | ||
} | ||
insert_ty(res, tcx, arg.clone(), ty_generics, cache); | ||
insert_ty(res, tcx, arg.clone(), ty_generics); | ||
} | ||
} | ||
|
||
/// 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, | ||
fn get_fn_inputs_and_outputs<'tcx>( | ||
func: &Function, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
tcx: TyCtxt<'tcx>, | ||
cache: &Cache, | ||
) -> (Vec<TypeWithKind>, Vec<TypeWithKind>) { | ||
let decl = &func.decl; | ||
let generics = &func.generics; | ||
|
||
let mut all_types = Vec::new(); | ||
for arg in decl.inputs.values.iter() { | ||
if arg.type_.is_self_type() { | ||
continue; | ||
} | ||
let mut args = Vec::new(); | ||
get_real_types(generics, &arg.type_, tcx, 0, &mut args, cache); | ||
add_generics_and_bounds_as_types(generics, &arg.type_, tcx, 0, &mut args); | ||
if !args.is_empty() { | ||
all_types.extend(args); | ||
} else { | ||
|
@@ -423,7 +417,7 @@ crate fn get_all_types<'tcx>( | |
let mut ret_types = Vec::new(); | ||
match decl.output { | ||
FnRetTy::Return(ref return_type) => { | ||
get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache); | ||
add_generics_and_bounds_as_types(generics, return_type, tcx, 0, &mut ret_types); | ||
if ret_types.is_empty() { | ||
if let Some(kind) = | ||
return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// check-pass | ||
|
||
// Minimization of issue #59502 | ||
|
||
trait MyTrait<T> { | ||
type Output; | ||
} | ||
|
||
pub fn pow<T: MyTrait<T, Output = T>>(arg: T) -> T { | ||
arg | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch!