diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
commit | 631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch) | |
tree | a1b87c8f8cad01cf18f7c5f57a08f102771ed303 /src/librustdoc/clean/mod.rs | |
parent | Adding debian version 1.69.0+dfsg1-1. (diff) | |
download | rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/librustdoc/clean/mod.rs')
-rw-r--r-- | src/librustdoc/clean/mod.rs | 288 |
1 files changed, 109 insertions, 179 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3edc2cd2e..5fa0c120f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,25 +21,24 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; +use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::TypeVisitableExt; -use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, EarlyBinder, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, ExpnKind}; -use std::assert_matches::assert_matches; +use std::borrow::Cow; use std::collections::hash_map::Entry; use std::collections::BTreeMap; -use std::default::Default; use std::hash::Hash; use std::mem; use thin_vec::ThinVec; -use crate::clean::inline::merge_attrs; use crate::core::{self, DocContext, ImplTraitParam}; use crate::formats::item_type::ItemType; use crate::visit_ast::Module as DocModule; @@ -270,15 +269,7 @@ fn clean_where_predicate<'tcx>( let bound_params = wbp .bound_generic_params .iter() - .map(|param| { - // Higher-ranked params must be lifetimes. - // Higher-ranked lifetimes can't have bounds. - assert_matches!( - param, - hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. } - ); - Lifetime(param.name.ident().name) - }) + .map(|param| clean_generic_param(cx, None, param)) .collect(); WherePredicate::BoundPredicate { ty: clean_ty(wbp.bounded_ty, cx), @@ -324,7 +315,7 @@ pub(crate) fn clean_predicate<'tcx>( ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::Subtype(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) @@ -410,7 +401,7 @@ fn clean_projection_predicate<'tcx>( .collect_referenced_late_bound_regions(&pred) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) if br.is_named() => Some(Lifetime(name)), + ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)), _ => None, }) .collect(); @@ -427,7 +418,7 @@ fn clean_projection<'tcx>( cx: &mut DocContext<'tcx>, def_id: Option<DefId>, ) -> Type { - if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder { + if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) { let bounds = cx .tcx .explicit_item_bounds(ty.skip_binder().def_id) @@ -508,7 +499,6 @@ fn clean_generic_param_def<'tcx>( ty::GenericParamDefKind::Const { has_default } => ( def.name, GenericParamDefKind::Const { - did: def.def_id, ty: Box::new(clean_middle_ty( ty::Binder::dummy( cx.tcx @@ -578,7 +568,6 @@ fn clean_generic_param<'tcx>( hir::GenericParamKind::Const { ty, default } => ( param.name.ident().name, GenericParamDefKind::Const { - did: param.def_id.to_def_id(), ty: Box::new(clean_ty(ty, cx)), default: default .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())), @@ -831,7 +820,7 @@ fn clean_ty_generics<'tcx>( p.get_bound_params() .into_iter() .flatten() - .map(|param| GenericParamDef::lifetime(param.0)) + .cloned() .collect(), )); } @@ -919,6 +908,38 @@ fn clean_ty_generics<'tcx>( } } +fn clean_proc_macro<'tcx>( + item: &hir::Item<'tcx>, + name: &mut Symbol, + kind: MacroKind, + cx: &mut DocContext<'tcx>, +) -> ItemKind { + let attrs = cx.tcx.hir().attrs(item.hir_id()); + if kind == MacroKind::Derive && + let Some(derive_name) = attrs + .lists(sym::proc_macro_derive) + .find_map(|mi| mi.ident()) + { + *name = derive_name.name; + } + + let mut helpers = Vec::new(); + for mi in attrs.lists(sym::proc_macro_derive) { + if !mi.has_name(sym::attributes) { + continue; + } + + if let Some(list) = mi.meta_item_list() { + for inner_mi in list { + if let Some(ident) = inner_mi.ident() { + helpers.push(ident.name); + } + } + } + } + ProcMacroItem(ProcMacro { kind, helpers }) +} + fn clean_fn_or_proc_macro<'tcx>( item: &hir::Item<'tcx>, sig: &hir::FnSig<'tcx>, @@ -940,31 +961,7 @@ fn clean_fn_or_proc_macro<'tcx>( } }); match macro_kind { - Some(kind) => { - if kind == MacroKind::Derive { - *name = attrs - .lists(sym::proc_macro_derive) - .find_map(|mi| mi.ident()) - .expect("proc-macro derives require a name") - .name; - } - - let mut helpers = Vec::new(); - for mi in attrs.lists(sym::proc_macro_derive) { - if !mi.has_name(sym::attributes) { - continue; - } - - if let Some(list) = mi.meta_item_list() { - for inner_mi in list { - if let Some(ident) = inner_mi.ident() { - helpers.push(ident.name); - } - } - } - } - ProcMacroItem(ProcMacro { kind, helpers }) - } + Some(kind) => clean_proc_macro(item, name, kind, cx), None => { let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id)); clean_fn_decl_legacy_const_generics(&mut func, attrs); @@ -2013,7 +2010,8 @@ fn clean_generic_args<'tcx>( generic_args: &hir::GenericArgs<'tcx>, cx: &mut DocContext<'tcx>, ) -> GenericArgs { - if generic_args.parenthesized { + // FIXME(return_type_notation): Fix RTN parens rendering + if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { let output = clean_ty(generic_args.bindings[0].ty(), cx); let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None }; let inputs = @@ -2066,110 +2064,44 @@ fn clean_bare_fn_ty<'tcx>( BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params } } -/// This visitor is used to go through only the "top level" of a item and not enter any sub -/// item while looking for a given `Ident` which is stored into `item` if found. -struct OneLevelVisitor<'hir> { - map: rustc_middle::hir::map::Map<'hir>, - item: Option<&'hir hir::Item<'hir>>, - looking_for: Ident, +pub(crate) fn reexport_chain<'tcx>( + tcx: TyCtxt<'tcx>, + import_def_id: LocalDefId, target_def_id: LocalDefId, -} - -impl<'hir> OneLevelVisitor<'hir> { - fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self { - Self { map, item: None, looking_for: Ident::empty(), target_def_id } - } - - fn reset(&mut self, looking_for: Ident) { - self.looking_for = looking_for; - self.item = None; - } -} - -impl<'hir> hir::intravisit::Visitor<'hir> for OneLevelVisitor<'hir> { - type NestedFilter = rustc_middle::hir::nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.map - } - - fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { - if self.item.is_none() - && item.ident == self.looking_for - && (matches!(item.kind, hir::ItemKind::Use(_, _)) - || item.owner_id.def_id == self.target_def_id) +) -> &'tcx [Reexport] { + for child in tcx.module_children_reexports(tcx.local_parent(import_def_id)) { + if child.res.opt_def_id() == Some(target_def_id.to_def_id()) + && child.reexport_chain[0].id() == Some(import_def_id.to_def_id()) { - self.item = Some(item); + return &child.reexport_chain; } } + &[] } -/// Because a `Use` item directly links to the imported item, we need to manually go through each -/// import one by one. To do so, we go to the parent item and look for the `Ident` into it. Then, -/// if we found the "end item" (the imported one), we stop there because we don't need its -/// documentation. Otherwise, we repeat the same operation until we find the "end item". +/// Collect attributes from the whole import chain. fn get_all_import_attributes<'hir>( - mut item: &hir::Item<'hir>, - tcx: TyCtxt<'hir>, + cx: &mut DocContext<'hir>, + import_def_id: LocalDefId, target_def_id: LocalDefId, - attributes: &mut Vec<ast::Attribute>, is_inline: bool, -) { +) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> { + let mut attrs = Vec::new(); let mut first = true; - let hir_map = tcx.hir(); - let mut visitor = OneLevelVisitor::new(hir_map, target_def_id); - let mut visited = FxHashSet::default(); - - // If the item is an import and has at least a path with two parts, we go into it. - while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) { + for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id) + .iter() + .flat_map(|reexport| reexport.id()) + { + let import_attrs = inline::load_attrs(cx, def_id); if first { // This is the "original" reexport so we get all its attributes without filtering them. - attributes.extend_from_slice(hir_map.attrs(item.hir_id())); + attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect(); first = false; } else { - add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline); - } - - let def_id = if let [.., parent_segment, _] = &path.segments { - match parent_segment.res { - hir::def::Res::Def(_, def_id) => def_id, - _ if parent_segment.ident.name == kw::Crate => { - // In case the "parent" is the crate, it'll give `Res::Err` so we need to - // circumvent it this way. - tcx.parent(item.owner_id.def_id.to_def_id()) - } - _ => break, - } - } else { - // If the path doesn't have a parent, then the parent is the current module. - tcx.parent(item.owner_id.def_id.to_def_id()) - }; - - let Some(parent) = hir_map.get_if_local(def_id) else { break }; - - // We get the `Ident` we will be looking for into `item`. - let looking_for = path.segments[path.segments.len() - 1].ident; - visitor.reset(looking_for); - - match parent { - hir::Node::Item(parent_item) => { - hir::intravisit::walk_item(&mut visitor, parent_item); - } - hir::Node::Crate(m) => { - hir::intravisit::walk_mod( - &mut visitor, - m, - tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()), - ); - } - _ => break, - } - if let Some(i) = visitor.item { - item = i; - } else { - break; + add_without_unwanted_attributes(&mut attrs, import_attrs, is_inline, Some(def_id)); } } + attrs } fn filter_tokens_from_list( @@ -2215,17 +2147,24 @@ fn filter_tokens_from_list( /// * `doc(inline)` /// * `doc(no_inline)` /// * `doc(hidden)` -fn add_without_unwanted_attributes( - attrs: &mut Vec<ast::Attribute>, - new_attrs: &[ast::Attribute], +fn add_without_unwanted_attributes<'hir>( + attrs: &mut Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)>, + new_attrs: &'hir [ast::Attribute], is_inline: bool, + import_parent: Option<DefId>, ) { - // If it's `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything. + // If it's not `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything. if !is_inline { - attrs.extend_from_slice(new_attrs); + for attr in new_attrs { + attrs.push((Cow::Borrowed(attr), import_parent)); + } return; } for attr in new_attrs { + if matches!(attr.kind, ast::AttrKind::DocComment(..)) { + attrs.push((Cow::Borrowed(attr), import_parent)); + continue; + } let mut attr = attr.clone(); match attr.kind { ast::AttrKind::Normal(ref mut normal) => { @@ -2252,18 +2191,15 @@ fn add_without_unwanted_attributes( ) }); args.tokens = TokenStream::new(tokens); - attrs.push(attr); + attrs.push((Cow::Owned(attr), import_parent)); } ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => { - attrs.push(attr); - continue; + attrs.push((Cow::Owned(attr), import_parent)); } } } } - ast::AttrKind::DocComment(..) => { - attrs.push(attr); - } + _ => unreachable!(), } } } @@ -2318,16 +2254,17 @@ fn clean_maybe_renamed_item<'tcx>( fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), - // proc macros can have a name set by attributes - ItemKind::Fn(ref sig, generics, body_id) => { - clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) - } - ItemKind::Macro(ref macro_def, _) => { + ItemKind::Macro(ref macro_def, MacroKind::Bang) => { let ty_vis = cx.tcx.visibility(def_id); MacroItem(Macro { source: display_macro_source(cx, name, macro_def, def_id, ty_vis), }) } + ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), + // proc macros can have a name set by attributes + ItemKind::Fn(ref sig, generics, body_id) => { + clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) + } ItemKind::Trait(_, _, generics, bounds, item_ids) => { let items = item_ids .iter() @@ -2350,26 +2287,28 @@ fn clean_maybe_renamed_item<'tcx>( _ => unreachable!("not yet converted"), }; - let mut import_attrs = Vec::new(); - let mut target_attrs = Vec::new(); - if let Some(import_id) = import_id && - let Some(hir::Node::Item(use_node)) = cx.tcx.hir().find_by_def_id(import_id) - { - let is_inline = inline::load_attrs(cx, import_id.to_def_id()).lists(sym::doc).get_word_attr(sym::inline).is_some(); - // Then we get all the various imports' attributes. - get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut import_attrs, is_inline); - add_without_unwanted_attributes(&mut target_attrs, inline::load_attrs(cx, def_id), is_inline); + let target_attrs = inline::load_attrs(cx, def_id); + let attrs = if let Some(import_id) = import_id { + let is_inline = inline::load_attrs(cx, import_id.to_def_id()) + .lists(sym::doc) + .get_word_attr(sym::inline) + .is_some(); + let mut attrs = + get_all_import_attributes(cx, import_id, item.owner_id.def_id, is_inline); + add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); + attrs } else { // We only keep the item's attributes. - target_attrs.extend_from_slice(inline::load_attrs(cx, def_id)); - } + target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect() + }; - let import_parent = import_id.map(|import_id| cx.tcx.local_parent(import_id).to_def_id()); - let (attrs, cfg) = merge_attrs(cx, import_parent, &target_attrs, Some(&import_attrs)); + let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg); + let attrs = + Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false); let mut item = Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg); - item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id()); + item.inline_stmt_id = import_id.map(|local| local.to_def_id()); vec![item] }) } @@ -2450,22 +2389,17 @@ fn clean_extern_crate<'tcx>( Some(l) => attr::list_contains_name(&l, sym::inline), None => false, } - }); + }) + && !cx.output_format.is_json(); let krate_owner_def_id = krate.owner_id.to_def_id(); if please_inline { - let mut visited = DefIdSet::default(); - - let res = Res::Def(DefKind::Mod, crate_def_id); - if let Some(items) = inline::try_inline( cx, - cx.tcx.parent_module(krate.hir_id()).to_def_id(), - Some(krate_owner_def_id), - res, + Res::Def(DefKind::Mod, crate_def_id), name, - Some(attrs), - &mut visited, + Some((attrs, Some(krate_owner_def_id))), + &mut Default::default(), ) { return items; } @@ -2589,17 +2523,13 @@ fn clean_use_statement_inner<'tcx>( denied = true; } if !denied { - let mut visited = DefIdSet::default(); let import_def_id = import.owner_id.to_def_id(); - if let Some(mut items) = inline::try_inline( cx, - cx.tcx.parent_module(import.hir_id()).to_def_id(), - Some(import_def_id), path.res, name, - Some(attrs), - &mut visited, + Some((attrs, Some(import_def_id))), + &mut Default::default(), ) { items.push(Item::from_def_id_and_parts( import_def_id, |