1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::hash::{Hash, Hasher};
4 use std::iter::FromIterator;
5 use std::lazy::SyncOnceCell as OnceCell;
6 use std::path::PathBuf;
11 use arrayvec::ArrayVec;
14 use rustc_ast::util::comments::beautify_doc_string;
15 use rustc_ast::{self as ast, AttrStyle};
16 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
17 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18 use rustc_data_structures::thin_vec::ThinVec;
20 use rustc_hir::def::{CtorKind, DefKind, Res};
21 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
22 use rustc_hir::lang_items::LangItem;
23 use rustc_hir::{BodyId, Mutability};
24 use rustc_index::vec::IndexVec;
25 use rustc_middle::ty::{self, TyCtxt};
26 use rustc_session::Session;
27 use rustc_span::hygiene::MacroKind;
28 use rustc_span::source_map::DUMMY_SP;
29 use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
30 use rustc_span::{self, FileName, Loc};
31 use rustc_target::abi::VariantIdx;
32 use rustc_target::spec::abi::Abi;
34 use crate::clean::cfg::Cfg;
35 use crate::clean::external_path;
36 use crate::clean::inline::{self, print_inlined_const};
37 use crate::clean::types::Type::{QPath, ResolvedPath};
38 use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
39 use crate::clean::Clean;
40 use crate::core::DocContext;
41 use crate::formats::cache::Cache;
42 use crate::formats::item_type::ItemType;
43 use crate::html::render::cache::ExternalLocation;
44 use crate::html::render::Context;
47 use self::ItemKind::*;
51 crate type ItemIdSet = FxHashSet<ItemId>;
53 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
55 /// A "normal" item that uses a [`DefId`] for identification.
57 /// Identifier that is used for auto traits.
58 Auto { trait_: DefId, for_: DefId },
59 /// Identifier that is used for blanket implementations.
60 Blanket { impl_id: DefId, for_: DefId },
61 /// Identifier for primitive types.
62 Primitive(PrimitiveType, CrateNum),
67 crate fn is_local(self) -> bool {
69 ItemId::Auto { for_: id, .. }
70 | ItemId::Blanket { for_: id, .. }
71 | ItemId::DefId(id) => id.is_local(),
72 ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
78 crate fn expect_def_id(self) -> DefId {
80 .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
84 crate fn as_def_id(self) -> Option<DefId> {
86 ItemId::DefId(id) => Some(id),
92 crate fn krate(self) -> CrateNum {
94 ItemId::Auto { for_: id, .. }
95 | ItemId::Blanket { for_: id, .. }
96 | ItemId::DefId(id) => id.krate,
97 ItemId::Primitive(_, krate) => krate,
102 crate fn index(self) -> Option<DefIndex> {
104 ItemId::DefId(id) => Some(id.index),
110 impl From<DefId> for ItemId {
111 fn from(id: DefId) -> Self {
116 #[derive(Clone, Debug)]
121 crate externs: Vec<ExternalCrate>,
122 crate primitives: ThinVec<(DefId, PrimitiveType)>,
123 /// Only here so that they can be filtered through the rustdoc passes.
124 crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
125 crate collapsed: bool,
128 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
129 #[derive(Clone, Debug)]
130 crate struct TraitWithExtraInfo {
132 crate is_notable: bool,
135 #[derive(Copy, Clone, Debug)]
136 crate struct ExternalCrate {
137 crate crate_num: CrateNum,
142 crate fn def_id(&self) -> DefId {
143 DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
146 crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
147 let krate_span = tcx.def_span(self.def_id());
148 tcx.sess.source_map().span_to_filename(krate_span)
151 crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
152 tcx.crate_name(self.crate_num)
155 crate fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
156 match self.src(tcx) {
157 FileName::Real(ref p) => match p.local_path_if_available().parent() {
158 Some(p) => p.to_path_buf(),
159 None => PathBuf::new(),
165 /// Attempts to find where an external crate is located, given that we're
166 /// rendering in to the specified source destination.
169 extern_url: Option<&str>,
170 extern_url_takes_precedence: bool,
171 dst: &std::path::Path,
173 ) -> ExternalLocation {
174 use ExternalLocation::*;
176 fn to_remote(url: impl ToString) -> ExternalLocation {
177 let mut url = url.to_string();
178 if !url.ends_with('/') {
184 // See if there's documentation generated into the local directory
185 // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
186 // Make sure to call `location()` by that time.
187 let local_location = dst.join(&*self.name(tcx).as_str());
188 if local_location.is_dir() {
192 if extern_url_takes_precedence {
193 if let Some(url) = extern_url {
194 return to_remote(url);
198 // Failing that, see if there's an attribute specifying where to find this
200 let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
203 .filter(|a| a.has_name(sym::html_root_url))
204 .filter_map(|a| a.value_str())
207 .or(extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
208 .unwrap_or(Unknown) // Well, at least we tried.
211 crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
212 let root = self.def_id();
214 let as_keyword = |res: Res<!>| {
215 if let Res::Def(DefKind::Mod, def_id) = res {
216 let attrs = tcx.get_attrs(def_id);
217 let mut keyword = None;
218 for attr in attrs.lists(sym::doc) {
219 if attr.has_name(sym::keyword) {
220 if let Some(v) = attr.value_str() {
226 return keyword.map(|p| (def_id, p));
237 let item = tcx.hir().item(id);
239 hir::ItemKind::Mod(_) => {
240 as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
242 hir::ItemKind::Use(ref path, hir::UseKind::Single)
243 if item.vis.node.is_pub() =>
245 as_keyword(path.res.expect_non_local())
246 .map(|(_, prim)| (id.def_id.to_def_id(), prim))
253 tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
257 crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
258 let root = self.def_id();
260 // Collect all inner modules which are tagged as implementations of
263 // Note that this loop only searches the top-level items of the crate,
264 // and this is intentional. If we were to search the entire crate for an
265 // item tagged with `#[doc(primitive)]` then we would also have to
266 // search the entirety of external modules for items tagged
267 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
268 // all that metadata unconditionally).
270 // In order to keep the metadata load under control, the
271 // `#[doc(primitive)]` feature is explicitly designed to only allow the
272 // primitive tags to show up as the top level items in a crate.
274 // Also note that this does not attempt to deal with modules tagged
275 // duplicately for the same primitive. This is handled later on when
276 // rendering by delegating everything to a hash map.
277 let as_primitive = |res: Res<!>| {
278 if let Res::Def(DefKind::Mod, def_id) = res {
279 let attrs = tcx.get_attrs(def_id);
281 for attr in attrs.lists(sym::doc) {
282 if let Some(v) = attr.value_str() {
283 if attr.has_name(sym::primitive) {
284 prim = PrimitiveType::from_symbol(v);
288 // FIXME: should warn on unknown primitives?
292 return prim.map(|p| (def_id, p));
304 let item = tcx.hir().item(id);
306 hir::ItemKind::Mod(_) => {
307 as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
309 hir::ItemKind::Use(ref path, hir::UseKind::Single)
310 if item.vis.node.is_pub() =>
312 as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
313 // Pretend the primitive is local.
314 (id.def_id.to_def_id(), prim)
322 tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
327 /// Anything with a source location and set of attributes and, optionally, a
328 /// name. That is, anything that can be documented. This doesn't correspond
329 /// directly to the AST's concept of an item; it's a strict superset.
330 #[derive(Clone, Debug)]
332 /// The name of this item.
333 /// Optional because not every item has a name, e.g. impls.
334 crate name: Option<Symbol>,
335 crate attrs: Box<Attributes>,
336 crate visibility: Visibility,
337 /// Information about this item that is specific to what kind of item it is.
338 /// E.g., struct vs enum vs function.
339 crate kind: Box<ItemKind>,
340 crate def_id: ItemId,
342 crate cfg: Option<Arc<Cfg>>,
345 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
346 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
347 rustc_data_structures::static_assert_size!(Item, 56);
349 crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
350 Span::new(def_id.as_local().map_or_else(
351 || tcx.def_span(def_id),
354 hir.span_with_body(hir.local_def_id_to_hir_id(local))
360 crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
361 self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
364 crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
365 self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
368 crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
369 self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
372 crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
373 self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
376 crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
377 let kind = match &*self.kind {
378 ItemKind::StrippedItem(k) => k,
381 if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
386 self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy())
390 crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
391 crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
394 /// Finds the `doc` attribute as a NameValue and returns the corresponding
396 crate fn doc_value(&self) -> Option<String> {
397 self.attrs.doc_value()
400 /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
401 /// `hir_id` to a [`DefId`]
402 pub fn from_hir_id_and_parts(
404 name: Option<Symbol>,
406 cx: &mut DocContext<'_>,
408 Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
411 pub fn from_def_id_and_parts(
413 name: Option<Symbol>,
415 cx: &mut DocContext<'_>,
417 let ast_attrs = cx.tcx.get_attrs(def_id);
419 Self::from_def_id_and_attrs_and_parts(
423 box ast_attrs.clean(cx),
425 ast_attrs.cfg(cx.sess()),
429 pub fn from_def_id_and_attrs_and_parts(
431 name: Option<Symbol>,
433 attrs: Box<Attributes>,
434 cx: &mut DocContext<'_>,
435 cfg: Option<Arc<Cfg>>,
437 trace!("name={:?}, def_id={:?}", name, def_id);
440 def_id: def_id.into(),
444 visibility: cx.tcx.visibility(def_id).clean(cx),
449 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
451 crate fn collapsed_doc_value(&self) -> Option<String> {
452 self.attrs.collapsed_doc_value()
455 crate fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
456 use crate::html::format::href;
461 .map_or(&[][..], |v| v.as_slice())
463 .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
465 if let Ok((mut href, ..)) = href(*did, cx) {
467 if let Some(ref fragment) = *fragment {
469 href.push_str(fragment);
472 original_text: s.clone(),
473 new_text: link_text.clone(),
483 /// Find a list of all link names, without finding their href.
485 /// This is used for generating summary text, which does not include
486 /// the link text, but does need to know which `[]`-bracketed names
487 /// are actually links.
488 crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
492 .map_or(&[][..], |v| v.as_slice())
494 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
495 original_text: s.clone(),
496 new_text: link_text.clone(),
502 crate fn is_crate(&self) -> bool {
503 self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
505 crate fn is_mod(&self) -> bool {
506 self.type_() == ItemType::Module
508 crate fn is_trait(&self) -> bool {
509 self.type_() == ItemType::Trait
511 crate fn is_struct(&self) -> bool {
512 self.type_() == ItemType::Struct
514 crate fn is_enum(&self) -> bool {
515 self.type_() == ItemType::Enum
517 crate fn is_variant(&self) -> bool {
518 self.type_() == ItemType::Variant
520 crate fn is_associated_type(&self) -> bool {
521 self.type_() == ItemType::AssocType
523 crate fn is_associated_const(&self) -> bool {
524 self.type_() == ItemType::AssocConst
526 crate fn is_method(&self) -> bool {
527 self.type_() == ItemType::Method
529 crate fn is_ty_method(&self) -> bool {
530 self.type_() == ItemType::TyMethod
532 crate fn is_typedef(&self) -> bool {
533 self.type_() == ItemType::Typedef
535 crate fn is_primitive(&self) -> bool {
536 self.type_() == ItemType::Primitive
538 crate fn is_union(&self) -> bool {
539 self.type_() == ItemType::Union
541 crate fn is_import(&self) -> bool {
542 self.type_() == ItemType::Import
544 crate fn is_extern_crate(&self) -> bool {
545 self.type_() == ItemType::ExternCrate
547 crate fn is_keyword(&self) -> bool {
548 self.type_() == ItemType::Keyword
550 crate fn is_stripped(&self) -> bool {
552 StrippedItem(..) => true,
553 ImportItem(ref i) => !i.should_be_displayed,
557 crate fn has_stripped_fields(&self) -> Option<bool> {
559 StructItem(ref _struct) => Some(_struct.fields_stripped),
560 UnionItem(ref union) => Some(union.fields_stripped),
561 VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
566 crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
567 self.stability(tcx).as_ref().and_then(|ref s| {
568 let mut classes = Vec::with_capacity(2);
570 if s.level.is_unstable() {
571 classes.push("unstable");
574 // FIXME: what about non-staged API items that are deprecated?
575 if self.deprecation(tcx).is_some() {
576 classes.push("deprecated");
579 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
583 crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
584 match self.stability(tcx)?.level {
585 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
586 StabilityLevel::Unstable { .. } => None,
590 crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
591 match self.const_stability(tcx)?.level {
592 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
593 StabilityLevel::Unstable { .. } => None,
597 crate fn is_non_exhaustive(&self) -> bool {
598 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
601 /// Returns a documentation-level item type from the item.
602 crate fn type_(&self) -> ItemType {
606 crate fn is_default(&self) -> bool {
608 ItemKind::MethodItem(_, Some(defaultness)) => {
609 defaultness.has_value() && !defaultness.is_final()
616 #[derive(Clone, Debug)]
617 crate enum ItemKind {
619 /// The crate's name, *not* the name it's imported as.
626 FunctionItem(Function),
628 TypedefItem(Typedef, bool /* is associated type */),
629 OpaqueTyItem(OpaqueTy),
631 ConstantItem(Constant),
633 TraitAliasItem(TraitAlias),
635 /// A method signature only. Used for required methods in traits (ie,
636 /// non-default-methods).
637 TyMethodItem(Function),
638 /// A method with a body.
639 MethodItem(Function, Option<hir::Defaultness>),
640 StructFieldItem(Type),
641 VariantItem(Variant),
642 /// `fn`s from an extern block
643 ForeignFunctionItem(Function),
644 /// `static`s from an extern block
645 ForeignStaticItem(Static),
646 /// `type`s from an extern block
649 ProcMacroItem(ProcMacro),
650 PrimitiveItem(PrimitiveType),
651 AssocConstItem(Type, Option<String>),
652 /// An associated item in a trait or trait impl.
654 /// The bounds may be non-empty if there is a `where` clause.
655 /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
656 AssocTypeItem(Vec<GenericBound>, Option<Type>),
657 /// An item that has been stripped by a rustdoc pass
658 StrippedItem(Box<ItemKind>),
663 /// Some items contain others such as structs (for their fields) and Enums
664 /// (for their variants). This method returns those contained items.
665 crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
667 StructItem(s) => s.fields.iter(),
668 UnionItem(u) => u.fields.iter(),
669 VariantItem(Variant::Struct(v)) => v.fields.iter(),
670 VariantItem(Variant::Tuple(v)) => v.iter(),
671 EnumItem(e) => e.variants.iter(),
672 TraitItem(t) => t.items.iter(),
673 ImplItem(i) => i.items.iter(),
674 ModuleItem(m) => m.items.iter(),
675 ExternCrateItem { .. }
687 | ForeignFunctionItem(_)
688 | ForeignStaticItem(_)
693 | AssocConstItem(_, _)
694 | AssocTypeItem(_, _)
696 | KeywordItem(_) => [].iter(),
701 #[derive(Clone, Debug)]
702 crate struct Module {
703 crate items: Vec<Item>,
707 crate struct ListAttributesIter<'a> {
708 attrs: slice::Iter<'a, ast::Attribute>,
709 current_list: vec::IntoIter<ast::NestedMetaItem>,
713 impl<'a> Iterator for ListAttributesIter<'a> {
714 type Item = ast::NestedMetaItem;
716 fn next(&mut self) -> Option<Self::Item> {
717 if let Some(nested) = self.current_list.next() {
721 for attr in &mut self.attrs {
722 if let Some(list) = attr.meta_item_list() {
723 if attr.has_name(self.name) {
724 self.current_list = list.into_iter();
725 if let Some(nested) = self.current_list.next() {
735 fn size_hint(&self) -> (usize, Option<usize>) {
736 let lower = self.current_list.len();
741 crate trait AttributesExt {
742 /// Finds an attribute as List and returns the list of attributes nested inside.
743 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
745 fn span(&self) -> Option<rustc_span::Span>;
747 fn inner_docs(&self) -> bool;
749 fn other_attrs(&self) -> Vec<ast::Attribute>;
751 fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
754 impl AttributesExt for [ast::Attribute] {
755 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
756 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
759 /// Return the span of the first doc-comment, if it exists.
760 fn span(&self) -> Option<rustc_span::Span> {
761 self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
764 /// Returns whether the first doc-comment is an inner attribute.
766 //// If there are no doc-comments, return true.
767 /// FIXME(#78591): Support both inner and outer attributes on the same item.
768 fn inner_docs(&self) -> bool {
769 self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
772 fn other_attrs(&self) -> Vec<ast::Attribute> {
773 self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
776 fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
777 let mut cfg = Cfg::True;
779 for attr in self.iter() {
781 if attr.doc_str().is_none() && attr.has_name(sym::doc) {
783 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
786 if !item.has_name(sym::cfg) {
790 if let Some(cfg_mi) = item
792 .and_then(|item| rustc_expand::config::parse_cfg(&item, sess))
794 match Cfg::parse(&cfg_mi) {
795 Ok(new_cfg) => cfg &= new_cfg,
796 Err(e) => sess.span_err(e.span, e.msg),
804 for attr in self.lists(sym::target_feature) {
805 if attr.has_name(sym::enable) {
806 if let Some(feat) = attr.value_str() {
807 let meta = attr::mk_name_value_item_str(
808 Ident::with_dummy_span(sym::target_feature),
812 if let Ok(feat_cfg) = Cfg::parse(&meta) {
819 if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
823 crate trait NestedAttributesExt {
824 /// Returns `true` if the attribute list contains a specific `Word`
825 fn has_word(self, word: Symbol) -> bool;
826 fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
829 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
830 NestedAttributesExt for I
832 fn has_word(self, word: Symbol) -> bool {
833 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
836 fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
837 self.find(|attr| attr.is_word() && attr.has_name(word))
841 /// A portion of documentation, extracted from a `#[doc]` attribute.
843 /// Each variant contains the line number within the complete doc-comment where the fragment
844 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
846 /// Included files are kept separate from inline doc comments so that proper line-number
847 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
848 /// kept separate because of issue #42760.
849 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
850 crate struct DocFragment {
852 crate span: rustc_span::Span,
853 /// The module this doc-comment came from.
855 /// This allows distinguishing between the original documentation and a pub re-export.
856 /// If it is `None`, the item was not re-exported.
857 crate parent_module: Option<DefId>,
859 crate kind: DocFragmentKind,
860 crate need_backline: bool,
864 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
865 crate enum DocFragmentKind {
866 /// A doc fragment created from a `///` or `//!` doc comment.
868 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
872 // The goal of this function is to apply the `DocFragment` transformations that are required when
873 // transforming into the final markdown. So the transformations in here are:
875 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
876 // multiple lines in case of `#[doc = ""]`).
877 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
878 // `need_backline` field).
879 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
880 let s = frag.doc.as_str();
881 let mut iter = s.lines().peekable();
882 while let Some(line) = iter.next() {
883 if line.chars().any(|c| !c.is_whitespace()) {
884 assert!(line.len() >= frag.indent);
885 out.push_str(&line[frag.indent..]);
889 if iter.peek().is_some() {
893 if frag.need_backline {
898 impl<'a> FromIterator<&'a DocFragment> for String {
899 fn from_iter<T>(iter: T) -> Self
901 T: IntoIterator<Item = &'a DocFragment>,
903 iter.into_iter().fold(String::new(), |mut acc, frag| {
904 add_doc_fragment(&mut acc, &frag);
910 /// A link that has not yet been rendered.
912 /// This link will be turned into a rendered link by [`Item::links`].
913 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
914 crate struct ItemLink {
915 /// The original link written in the markdown
916 pub(crate) link: String,
917 /// The link text displayed in the HTML.
919 /// This may not be the same as `link` if there was a disambiguator
920 /// in an intra-doc link (e.g. \[`fn@f`\])
921 pub(crate) link_text: String,
922 pub(crate) did: DefId,
923 /// The url fragment to append to the link
924 pub(crate) fragment: Option<String>,
927 pub struct RenderedLink {
928 /// The text the link was original written as.
930 /// This could potentially include disambiguators and backticks.
931 pub(crate) original_text: String,
932 /// The text to display in the HTML
933 pub(crate) new_text: String,
934 /// The URL to put in the `href`
935 pub(crate) href: String,
938 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
939 /// as well as doc comments.
940 #[derive(Clone, Debug, Default)]
941 crate struct Attributes {
942 crate doc_strings: Vec<DocFragment>,
943 crate other_attrs: Vec<ast::Attribute>,
947 crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
948 self.other_attrs.lists(name)
951 crate fn has_doc_flag(&self, flag: Symbol) -> bool {
952 for attr in &self.other_attrs {
953 if !attr.has_name(sym::doc) {
957 if let Some(items) = attr.meta_item_list() {
958 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
968 attrs: &[ast::Attribute],
969 additional_attrs: Option<(&[ast::Attribute], DefId)>,
971 let mut doc_strings: Vec<DocFragment> = vec![];
972 let mut doc_line = 0;
974 fn update_need_backline(doc_strings: &mut Vec<DocFragment>) {
975 if let Some(prev) = doc_strings.last_mut() {
976 prev.need_backline = true;
980 let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
981 if let Some(value) = attr.doc_str() {
982 trace!("got doc_str={:?}", value);
983 let value = beautify_doc_string(value);
984 let kind = if attr.is_doc_comment() {
985 DocFragmentKind::SugaredDoc
987 DocFragmentKind::RawDoc
991 doc_line += value.as_str().lines().count();
992 let frag = DocFragment {
998 need_backline: false,
1002 update_need_backline(&mut doc_strings);
1004 doc_strings.push(frag);
1012 // Additional documentation should be shown before the original documentation
1013 let other_attrs = additional_attrs
1015 .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
1017 .chain(attrs.iter().map(|attr| (attr, None)))
1018 .filter_map(clean_attr)
1021 Attributes { doc_strings, other_attrs }
1024 /// Finds the `doc` attribute as a NameValue and returns the corresponding
1026 crate fn doc_value(&self) -> Option<String> {
1027 let mut iter = self.doc_strings.iter();
1029 let ori = iter.next()?;
1030 let mut out = String::new();
1031 add_doc_fragment(&mut out, &ori);
1032 while let Some(new_frag) = iter.next() {
1033 if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module {
1036 add_doc_fragment(&mut out, &new_frag);
1038 if out.is_empty() { None } else { Some(out) }
1041 /// Return the doc-comments on this item, grouped by the module they came from.
1043 /// The module can be different if this is a re-export with added documentation.
1044 crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
1045 let mut ret = FxHashMap::default();
1047 for new_frag in self.doc_strings.iter() {
1048 let out = ret.entry(new_frag.parent_module).or_default();
1049 add_doc_fragment(out, &new_frag);
1054 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1056 crate fn collapsed_doc_value(&self) -> Option<String> {
1057 if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
1060 crate fn get_doc_aliases(&self) -> Box<[String]> {
1061 let mut aliases = FxHashSet::default();
1063 for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1064 if let Some(values) = attr.meta_item_list() {
1066 match l.literal().unwrap().kind {
1067 ast::LitKind::Str(s, _) => {
1068 aliases.insert(s.as_str().to_string());
1070 _ => unreachable!(),
1074 aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap());
1077 aliases.into_iter().collect::<Vec<String>>().into()
1081 impl PartialEq for Attributes {
1082 fn eq(&self, rhs: &Self) -> bool {
1083 self.doc_strings == rhs.doc_strings
1087 .map(|attr| attr.id)
1088 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1092 impl Eq for Attributes {}
1094 impl Hash for Attributes {
1095 fn hash<H: Hasher>(&self, hasher: &mut H) {
1096 self.doc_strings.hash(hasher);
1097 for attr in &self.other_attrs {
1098 attr.id.hash(hasher);
1103 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1104 crate enum GenericBound {
1105 TraitBound(PolyTrait, hir::TraitBoundModifier),
1110 crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1111 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1112 let empty = cx.tcx.intern_substs(&[]);
1113 let path = external_path(cx, did, false, vec![], empty);
1114 inline::record_extern_fqn(cx, did, ItemType::Trait);
1115 GenericBound::TraitBound(
1116 PolyTrait { trait_: path, generic_params: Vec::new() },
1117 hir::TraitBoundModifier::Maybe,
1121 crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1122 use rustc_hir::TraitBoundModifier as TBM;
1123 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1124 if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() {
1131 crate fn get_poly_trait(&self) -> Option<PolyTrait> {
1132 if let GenericBound::TraitBound(ref p, _) = *self {
1133 return Some(p.clone());
1138 crate fn get_trait_path(&self) -> Option<Path> {
1139 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1140 Some(trait_.clone())
1147 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1148 crate struct Lifetime(pub Symbol);
1151 crate fn get_ref(&self) -> SymbolStr {
1155 crate fn statik() -> Lifetime {
1156 Lifetime(kw::StaticLifetime)
1159 crate fn elided() -> Lifetime {
1160 Lifetime(kw::UnderscoreLifetime)
1164 #[derive(Clone, Debug)]
1165 crate enum WherePredicate {
1166 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
1167 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1168 EqPredicate { lhs: Type, rhs: Type },
1171 impl WherePredicate {
1172 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1174 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1175 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1181 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1182 crate enum GenericParamDefKind {
1184 outlives: Vec<Lifetime>,
1188 bounds: Vec<GenericBound>,
1189 default: Option<Type>,
1190 synthetic: Option<hir::SyntheticTyParamKind>,
1195 default: Option<String>,
1199 impl GenericParamDefKind {
1200 crate fn is_type(&self) -> bool {
1201 matches!(self, GenericParamDefKind::Type { .. })
1204 // FIXME(eddyb) this either returns the default of a type parameter, or the
1205 // type of a `const` parameter. It seems that the intention is to *visit*
1206 // any embedded types, but `get_type` seems to be the wrong name for that.
1207 crate fn get_type(&self) -> Option<Type> {
1209 GenericParamDefKind::Type { default, .. } => default.clone(),
1210 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1211 GenericParamDefKind::Lifetime { .. } => None,
1216 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1217 crate struct GenericParamDef {
1219 crate kind: GenericParamDefKind,
1222 impl GenericParamDef {
1223 crate fn is_synthetic_type_param(&self) -> bool {
1225 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1226 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1230 crate fn is_type(&self) -> bool {
1234 crate fn get_type(&self) -> Option<Type> {
1235 self.kind.get_type()
1238 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1240 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1246 // maybe use a Generic enum and use Vec<Generic>?
1247 #[derive(Clone, Debug, Default)]
1248 crate struct Generics {
1249 crate params: Vec<GenericParamDef>,
1250 crate where_predicates: Vec<WherePredicate>,
1253 #[derive(Clone, Debug)]
1254 crate struct Function {
1256 crate generics: Generics,
1257 crate header: hir::FnHeader,
1260 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1261 crate struct FnDecl {
1262 crate inputs: Arguments,
1263 crate output: FnRetTy,
1264 crate c_variadic: bool,
1268 crate fn self_type(&self) -> Option<SelfTy> {
1269 self.inputs.values.get(0).and_then(|v| v.to_self())
1272 /// Returns the sugared return type for an async function.
1274 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1275 /// will return `i32`.
1279 /// This function will panic if the return type does not match the expected sugaring for async
1281 crate fn sugared_async_return_type(&self) -> FnRetTy {
1282 match &self.output {
1283 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1284 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1285 let bindings = trait_.bindings().unwrap();
1286 FnRetTy::Return(bindings[0].ty().clone())
1288 _ => panic!("unexpected desugaring of async function"),
1290 _ => panic!("unexpected desugaring of async function"),
1295 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1296 crate struct Arguments {
1297 crate values: Vec<Argument>,
1300 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1301 crate struct Argument {
1306 #[derive(Clone, PartialEq, Debug)]
1309 SelfBorrowed(Option<Lifetime>, Mutability),
1314 crate fn to_self(&self) -> Option<SelfTy> {
1315 if self.name != kw::SelfLower {
1318 if self.type_.is_self_type() {
1319 return Some(SelfValue);
1322 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1323 Some(SelfBorrowed(lifetime.clone(), mutability))
1325 _ => Some(SelfExplicit(self.type_.clone())),
1330 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1331 crate enum FnRetTy {
1336 impl GetDefId for FnRetTy {
1337 fn def_id(&self) -> Option<DefId> {
1339 Return(ref ty) => ty.def_id(),
1340 DefaultReturn => None,
1344 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1346 Return(ref ty) => ty.def_id_full(cache),
1347 DefaultReturn => None,
1352 #[derive(Clone, Debug)]
1353 crate struct Trait {
1354 crate unsafety: hir::Unsafety,
1355 crate items: Vec<Item>,
1356 crate generics: Generics,
1357 crate bounds: Vec<GenericBound>,
1358 crate is_auto: bool,
1361 #[derive(Clone, Debug)]
1362 crate struct TraitAlias {
1363 crate generics: Generics,
1364 crate bounds: Vec<GenericBound>,
1367 /// A trait reference, which may have higher ranked lifetimes.
1368 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1369 crate struct PolyTrait {
1371 crate generic_params: Vec<GenericParamDef>,
1374 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1375 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1377 /// A named type, which could be a trait.
1379 /// This is mostly Rustdoc's version of [`hir::Path`]. It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1380 ResolvedPath { path: Path, did: DefId },
1381 /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1382 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1383 /// A type parameter.
1385 /// A primitive (aka, builtin) type.
1386 Primitive(PrimitiveType),
1387 /// A function pointer: `extern "ABI" fn(...) -> ...`
1388 BareFunction(Box<BareFunctionDecl>),
1389 /// A tuple type: `(i32, &str)`.
1391 /// A slice type (does *not* include the `&`): `[i32]`
1395 /// The `String` field is a stringified version of the array's length parameter.
1396 Array(Box<Type>, String),
1397 /// A raw pointer type: `*const i32`, `*mut i32`
1398 RawPointer(Mutability, Box<Type>),
1399 /// A reference type: `&i32`, `&'a mut Foo`
1400 BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
1402 /// A qualified path to an associated item: `<Type as Trait>::Name`
1405 self_type: Box<Type>,
1406 /// FIXME: This is a hack that should be removed; see [this discussion][1].
1408 /// [1]: https://github.com/rust-lang/rust/pull/85479#discussion_r635729093
1409 self_def_id: Option<DefId>,
1413 /// A type that is inferred: `_`
1416 /// An `impl Trait`: `impl TraitA + TraitB + ...`
1417 ImplTrait(Vec<GenericBound>),
1420 crate trait GetDefId {
1421 /// Use this method to get the [`DefId`] of a [`clean`] AST node.
1422 /// This will return [`None`] when called on a primitive [`clean::Type`].
1423 /// Use [`Self::def_id_full`] if you want to include primitives.
1425 /// [`clean`]: crate::clean
1426 /// [`clean::Type`]: crate::clean::Type
1427 // FIXME: get rid of this function and always use `def_id_full`
1428 fn def_id(&self) -> Option<DefId>;
1430 /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1432 /// See [`Self::def_id`] for more.
1434 /// [clean]: crate::clean
1435 fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
1438 impl<T: GetDefId> GetDefId for Option<T> {
1439 fn def_id(&self) -> Option<DefId> {
1440 self.as_ref().and_then(|d| d.def_id())
1443 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1444 self.as_ref().and_then(|d| d.def_id_full(cache))
1449 crate fn primitive_type(&self) -> Option<PrimitiveType> {
1451 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1452 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1453 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1456 Some(PrimitiveType::Unit)
1458 Some(PrimitiveType::Tuple)
1461 RawPointer(..) => Some(PrimitiveType::RawPointer),
1462 BareFunction(..) => Some(PrimitiveType::Fn),
1467 /// Checks if this is a `T::Name` path for an associated type.
1468 crate fn is_assoc_ty(&self) -> bool {
1470 ResolvedPath { path, .. } => path.is_assoc_ty(),
1475 crate fn is_self_type(&self) -> bool {
1477 Generic(name) => name == kw::SelfUpper,
1482 crate fn generics(&self) -> Option<Vec<&Type>> {
1484 ResolvedPath { path, .. } => path.generics(),
1489 crate fn is_full_generic(&self) -> bool {
1490 matches!(self, Type::Generic(_))
1493 crate fn is_primitive(&self) -> bool {
1494 self.primitive_type().is_some()
1497 crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1498 let (self_, trait_, name) = match self {
1499 QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
1502 Some((&self_, trait_.def_id(), *name))
1505 fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1506 let t: PrimitiveType = match *self {
1507 ResolvedPath { did, .. } => return Some(did),
1508 DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
1509 Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1510 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1511 BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1516 PrimitiveType::Tuple
1519 BareFunction(..) => PrimitiveType::Fn,
1520 Slice(..) => PrimitiveType::Slice,
1521 Array(..) => PrimitiveType::Array,
1522 RawPointer(..) => PrimitiveType::RawPointer,
1523 QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1524 Generic(_) | Infer | ImplTrait(_) => return None,
1526 cache.and_then(|c| Primitive(t).def_id_full(c))
1530 impl GetDefId for Type {
1531 fn def_id(&self) -> Option<DefId> {
1532 self.inner_def_id(None)
1535 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1536 self.inner_def_id(Some(cache))
1540 /// A primitive (aka, builtin) type.
1542 /// This represents things like `i32`, `str`, etc.
1544 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1545 /// paths, like [`Self::Unit`].
1546 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1547 crate enum PrimitiveType {
1575 impl PrimitiveType {
1576 crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1577 use ast::{FloatTy, IntTy, UintTy};
1579 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1580 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1581 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1582 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1583 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1584 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1585 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1586 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1587 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1588 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1589 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1590 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1591 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1592 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1593 hir::PrimTy::Str => PrimitiveType::Str,
1594 hir::PrimTy::Bool => PrimitiveType::Bool,
1595 hir::PrimTy::Char => PrimitiveType::Char,
1599 crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1601 sym::isize => Some(PrimitiveType::Isize),
1602 sym::i8 => Some(PrimitiveType::I8),
1603 sym::i16 => Some(PrimitiveType::I16),
1604 sym::i32 => Some(PrimitiveType::I32),
1605 sym::i64 => Some(PrimitiveType::I64),
1606 sym::i128 => Some(PrimitiveType::I128),
1607 sym::usize => Some(PrimitiveType::Usize),
1608 sym::u8 => Some(PrimitiveType::U8),
1609 sym::u16 => Some(PrimitiveType::U16),
1610 sym::u32 => Some(PrimitiveType::U32),
1611 sym::u64 => Some(PrimitiveType::U64),
1612 sym::u128 => Some(PrimitiveType::U128),
1613 sym::bool => Some(PrimitiveType::Bool),
1614 sym::char => Some(PrimitiveType::Char),
1615 sym::str => Some(PrimitiveType::Str),
1616 sym::f32 => Some(PrimitiveType::F32),
1617 sym::f64 => Some(PrimitiveType::F64),
1618 sym::array => Some(PrimitiveType::Array),
1619 sym::slice => Some(PrimitiveType::Slice),
1620 sym::tuple => Some(PrimitiveType::Tuple),
1621 sym::unit => Some(PrimitiveType::Unit),
1622 sym::pointer => Some(PrimitiveType::RawPointer),
1623 sym::reference => Some(PrimitiveType::Reference),
1624 kw::Fn => Some(PrimitiveType::Fn),
1625 sym::never => Some(PrimitiveType::Never),
1630 crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
1631 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1634 crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>> {
1635 static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>> = OnceCell::new();
1637 CELL.get_or_init(move || {
1638 use self::PrimitiveType::*;
1640 let single = |a: Option<DefId>| a.into_iter().collect();
1641 let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_, 4> {
1642 a.into_iter().chain(b).collect()
1645 let lang_items = tcx.lang_items();
1647 Isize => single(lang_items.isize_impl()),
1648 I8 => single(lang_items.i8_impl()),
1649 I16 => single(lang_items.i16_impl()),
1650 I32 => single(lang_items.i32_impl()),
1651 I64 => single(lang_items.i64_impl()),
1652 I128 => single(lang_items.i128_impl()),
1653 Usize => single(lang_items.usize_impl()),
1654 U8 => single(lang_items.u8_impl()),
1655 U16 => single(lang_items.u16_impl()),
1656 U32 => single(lang_items.u32_impl()),
1657 U64 => single(lang_items.u64_impl()),
1658 U128 => single(lang_items.u128_impl()),
1659 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1660 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1661 Char => single(lang_items.char_impl()),
1662 Bool => single(lang_items.bool_impl()),
1663 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1668 .chain(lang_items.slice_u8_impl())
1669 .chain(lang_items.slice_alloc_impl())
1670 .chain(lang_items.slice_u8_alloc_impl())
1673 Array => single(lang_items.array_impl()),
1674 Tuple => ArrayVec::new(),
1675 Unit => ArrayVec::new(),
1680 .chain(lang_items.mut_ptr_impl())
1681 .chain(lang_items.const_slice_ptr_impl())
1682 .chain(lang_items.mut_slice_ptr_impl())
1685 Reference => ArrayVec::new(),
1686 Fn => ArrayVec::new(),
1687 Never => ArrayVec::new(),
1692 crate fn as_sym(&self) -> Symbol {
1693 use PrimitiveType::*;
1695 Isize => sym::isize,
1701 Usize => sym::usize,
1712 Array => sym::array,
1713 Slice => sym::slice,
1714 Tuple => sym::tuple,
1716 RawPointer => sym::pointer,
1717 Reference => sym::reference,
1719 Never => sym::never,
1723 /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1724 /// Panics if there is no such module.
1726 /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1727 /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1728 /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1729 /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1730 crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1731 static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1732 PRIMITIVE_LOCATIONS.get_or_init(|| {
1733 let mut primitive_locations = FxHashMap::default();
1734 // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1735 // This is a degenerate case that I don't plan to support.
1736 for &crate_num in tcx.crates(()) {
1737 let e = ExternalCrate { crate_num };
1738 let crate_name = e.name(tcx);
1739 debug!(?crate_num, ?crate_name);
1740 for &(def_id, prim) in &e.primitives(tcx) {
1741 // HACK: try to link to std instead where possible
1742 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1745 primitive_locations.insert(prim, def_id);
1748 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1749 for (def_id, prim) in local_primitives {
1750 primitive_locations.insert(prim, def_id);
1757 impl From<ast::IntTy> for PrimitiveType {
1758 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1760 ast::IntTy::Isize => PrimitiveType::Isize,
1761 ast::IntTy::I8 => PrimitiveType::I8,
1762 ast::IntTy::I16 => PrimitiveType::I16,
1763 ast::IntTy::I32 => PrimitiveType::I32,
1764 ast::IntTy::I64 => PrimitiveType::I64,
1765 ast::IntTy::I128 => PrimitiveType::I128,
1770 impl From<ast::UintTy> for PrimitiveType {
1771 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1773 ast::UintTy::Usize => PrimitiveType::Usize,
1774 ast::UintTy::U8 => PrimitiveType::U8,
1775 ast::UintTy::U16 => PrimitiveType::U16,
1776 ast::UintTy::U32 => PrimitiveType::U32,
1777 ast::UintTy::U64 => PrimitiveType::U64,
1778 ast::UintTy::U128 => PrimitiveType::U128,
1783 impl From<ast::FloatTy> for PrimitiveType {
1784 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1786 ast::FloatTy::F32 => PrimitiveType::F32,
1787 ast::FloatTy::F64 => PrimitiveType::F64,
1792 impl From<ty::IntTy> for PrimitiveType {
1793 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1795 ty::IntTy::Isize => PrimitiveType::Isize,
1796 ty::IntTy::I8 => PrimitiveType::I8,
1797 ty::IntTy::I16 => PrimitiveType::I16,
1798 ty::IntTy::I32 => PrimitiveType::I32,
1799 ty::IntTy::I64 => PrimitiveType::I64,
1800 ty::IntTy::I128 => PrimitiveType::I128,
1805 impl From<ty::UintTy> for PrimitiveType {
1806 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1808 ty::UintTy::Usize => PrimitiveType::Usize,
1809 ty::UintTy::U8 => PrimitiveType::U8,
1810 ty::UintTy::U16 => PrimitiveType::U16,
1811 ty::UintTy::U32 => PrimitiveType::U32,
1812 ty::UintTy::U64 => PrimitiveType::U64,
1813 ty::UintTy::U128 => PrimitiveType::U128,
1818 impl From<ty::FloatTy> for PrimitiveType {
1819 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1821 ty::FloatTy::F32 => PrimitiveType::F32,
1822 ty::FloatTy::F64 => PrimitiveType::F64,
1827 impl From<hir::PrimTy> for PrimitiveType {
1828 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1830 hir::PrimTy::Int(int_ty) => int_ty.into(),
1831 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1832 hir::PrimTy::Float(float_ty) => float_ty.into(),
1833 hir::PrimTy::Str => PrimitiveType::Str,
1834 hir::PrimTy::Bool => PrimitiveType::Bool,
1835 hir::PrimTy::Char => PrimitiveType::Char,
1840 #[derive(Copy, Clone, Debug)]
1841 crate enum Visibility {
1844 /// Visibility inherited from parent.
1846 /// For example, this is the visibility of private items and of enum variants.
1848 /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
1853 crate fn is_public(&self) -> bool {
1854 matches!(self, Visibility::Public)
1858 #[derive(Clone, Debug)]
1859 crate struct Struct {
1860 crate struct_type: CtorKind,
1861 crate generics: Generics,
1862 crate fields: Vec<Item>,
1863 crate fields_stripped: bool,
1866 #[derive(Clone, Debug)]
1867 crate struct Union {
1868 crate generics: Generics,
1869 crate fields: Vec<Item>,
1870 crate fields_stripped: bool,
1873 /// This is a more limited form of the standard Struct, different in that
1874 /// it lacks the things most items have (name, id, parameterization). Found
1875 /// only as a variant in an enum.
1876 #[derive(Clone, Debug)]
1877 crate struct VariantStruct {
1878 crate struct_type: CtorKind,
1879 crate fields: Vec<Item>,
1880 crate fields_stripped: bool,
1883 #[derive(Clone, Debug)]
1885 crate variants: IndexVec<VariantIdx, Item>,
1886 crate generics: Generics,
1887 crate variants_stripped: bool,
1890 #[derive(Clone, Debug)]
1891 crate enum Variant {
1894 Struct(VariantStruct),
1897 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
1898 /// and enforces calling [`rustc_span::Span::source_callsite()`].
1899 #[derive(Copy, Clone, Debug)]
1900 crate struct Span(rustc_span::Span);
1903 /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
1904 /// span will be updated to point to the macro invocation instead of the macro definition.
1906 /// (See rust-lang/rust#39726)
1907 crate fn new(sp: rustc_span::Span) -> Self {
1908 Self(sp.source_callsite())
1911 crate fn inner(&self) -> rustc_span::Span {
1915 crate fn dummy() -> Self {
1916 Self(rustc_span::DUMMY_SP)
1919 crate fn is_dummy(&self) -> bool {
1923 crate fn filename(&self, sess: &Session) -> FileName {
1924 sess.source_map().span_to_filename(self.0)
1927 crate fn lo(&self, sess: &Session) -> Loc {
1928 sess.source_map().lookup_char_pos(self.0.lo())
1931 crate fn hi(&self, sess: &Session) -> Loc {
1932 sess.source_map().lookup_char_pos(self.0.hi())
1935 crate fn cnum(&self, sess: &Session) -> CrateNum {
1936 // FIXME: is there a time when the lo and hi crate would be different?
1937 self.lo(sess).file.cnum
1941 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1944 crate segments: Vec<PathSegment>,
1948 crate fn def_id(&self) -> DefId {
1952 crate fn last(&self) -> Symbol {
1953 self.segments.last().expect("segments were empty").name
1956 crate fn last_name(&self) -> SymbolStr {
1957 self.segments.last().expect("segments were empty").name.as_str()
1960 crate fn whole_name(&self) -> String {
1961 self.segments.iter().map(|s| s.name.to_string()).intersperse("::".into()).collect()
1964 /// Checks if this is a `T::Name` path for an associated type.
1965 crate fn is_assoc_ty(&self) -> bool {
1967 Res::SelfTy(..) if self.segments.len() != 1 => true,
1968 Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
1969 Res::Def(DefKind::AssocTy, _) => true,
1974 crate fn generics(&self) -> Option<Vec<&Type>> {
1975 self.segments.last().and_then(|seg| {
1976 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1979 .filter_map(|arg| match arg {
1980 GenericArg::Type(ty) => Some(ty),
1991 crate fn bindings(&self) -> Option<&[TypeBinding]> {
1992 self.segments.last().and_then(|seg| {
1993 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2002 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2003 crate enum GenericArg {
2006 Const(Box<Constant>),
2010 // `GenericArg` can occur many times in a single `Path`, so make sure it
2011 // doesn't increase in size unexpectedly.
2012 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2013 rustc_data_structures::static_assert_size!(GenericArg, 80);
2015 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2016 crate enum GenericArgs {
2017 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
2018 Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
2021 // `GenericArgs` is in every `PathSegment`, so its size can significantly
2022 // affect rustdoc's memory usage.
2023 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2024 rustc_data_structures::static_assert_size!(GenericArgs, 56);
2026 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2027 crate struct PathSegment {
2029 crate args: GenericArgs,
2032 // `PathSegment` usually occurs multiple times in every `Path`, so its size can
2033 // significantly affect rustdoc's memory usage.
2034 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2035 rustc_data_structures::static_assert_size!(PathSegment, 64);
2037 #[derive(Clone, Debug)]
2038 crate struct Typedef {
2040 crate generics: Generics,
2041 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2042 /// alias instead of the final type. This will always have the final type, regardless of whether
2043 /// `type_` came from HIR or from metadata.
2045 /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
2047 crate item_type: Option<Type>,
2050 impl GetDefId for Typedef {
2051 fn def_id(&self) -> Option<DefId> {
2055 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
2056 self.type_.def_id_full(cache)
2060 #[derive(Clone, Debug)]
2061 crate struct OpaqueTy {
2062 crate bounds: Vec<GenericBound>,
2063 crate generics: Generics,
2066 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2067 crate struct BareFunctionDecl {
2068 crate unsafety: hir::Unsafety,
2069 crate generic_params: Vec<GenericParamDef>,
2074 #[derive(Clone, Debug)]
2075 crate struct Static {
2077 crate mutability: Mutability,
2078 crate expr: Option<BodyId>,
2081 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2082 crate struct Constant {
2084 crate kind: ConstantKind,
2087 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2088 crate enum ConstantKind {
2089 /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2090 /// `BodyId`, we need to handle it on its own.
2092 /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2093 /// by a DefId. So this field must be different from `Extern`.
2094 TyConst { expr: String },
2095 /// A constant (expression) that's not an item or associated item. These are usually found
2096 /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2097 /// used to define explicit discriminant values for enum variants.
2098 Anonymous { body: BodyId },
2099 /// A constant from a different crate.
2100 Extern { def_id: DefId },
2101 /// `const FOO: u32 = ...;`
2102 Local { def_id: DefId, body: BodyId },
2106 crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
2108 ConstantKind::TyConst { ref expr } => expr.clone(),
2109 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2110 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2111 print_const_expr(tcx, body)
2116 crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2118 ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2119 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2120 print_evaluated_const(tcx, def_id)
2125 crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2127 ConstantKind::TyConst { .. } => false,
2128 ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2129 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2131 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2132 is_literal_expr(tcx, body.hir_id)
2138 #[derive(Clone, Debug)]
2141 crate unsafety: hir::Unsafety,
2142 crate generics: Generics,
2143 crate trait_: Option<Path>,
2145 crate items: Vec<Item>,
2146 crate negative_polarity: bool,
2147 crate synthetic: bool,
2148 crate blanket_impl: Option<Box<Type>>,
2152 crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2155 .map(|t| t.def_id())
2156 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
2157 .unwrap_or_default()
2161 #[derive(Clone, Debug)]
2162 crate struct Import {
2163 crate kind: ImportKind,
2164 crate source: ImportSource,
2165 crate should_be_displayed: bool,
2169 crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
2170 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2173 crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2174 Self { kind: ImportKind::Glob, source, should_be_displayed }
2178 #[derive(Clone, Debug)]
2179 crate enum ImportKind {
2180 // use source as str;
2186 #[derive(Clone, Debug)]
2187 crate struct ImportSource {
2189 crate did: Option<DefId>,
2192 #[derive(Clone, Debug)]
2193 crate struct Macro {
2194 crate source: String,
2197 #[derive(Clone, Debug)]
2198 crate struct ProcMacro {
2199 crate kind: MacroKind,
2200 crate helpers: Vec<Symbol>,
2203 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2204 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2205 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2206 crate struct TypeBinding {
2208 crate kind: TypeBindingKind,
2211 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2212 crate enum TypeBindingKind {
2213 Equality { ty: Type },
2214 Constraint { bounds: Vec<GenericBound> },
2218 crate fn ty(&self) -> &Type {
2220 TypeBindingKind::Equality { ref ty } => ty,
2221 _ => panic!("expected equality type binding for parenthesized generic args"),