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;
7 use std::rc::Rc;
8 use std::sync::Arc;
9 use std::{slice, vec};
10 
11 use arrayvec::ArrayVec;
12 
13 use rustc_ast::attr;
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;
19 use rustc_hir as hir;
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;
33 
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::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
38 use crate::clean::Clean;
39 use crate::core::DocContext;
40 use crate::formats::cache::Cache;
41 use crate::formats::item_type::ItemType;
42 use crate::html::render::cache::ExternalLocation;
43 use crate::html::render::Context;
44 
45 crate use self::FnRetTy::*;
46 crate use self::ItemKind::*;
47 crate use self::SelfTy::*;
48 crate use self::Type::{
49     Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
50     RawPointer, Slice, Tuple,
51 };
52 crate use self::Visibility::{Inherited, Public};
53 
54 crate type ItemIdSet = FxHashSet<ItemId>;
55 
56 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
57 crate enum ItemId {
58     /// A "normal" item that uses a [`DefId`] for identification.
59     DefId(DefId),
60     /// Identifier that is used for auto traits.
61     Auto { trait_: DefId, for_: DefId },
62     /// Identifier that is used for blanket implementations.
63     Blanket { impl_id: DefId, for_: DefId },
64     /// Identifier for primitive types.
65     Primitive(PrimitiveType, CrateNum),
66 }
67 
68 impl ItemId {
69     #[inline]
is_local(self) -> bool70     crate fn is_local(self) -> bool {
71         match self {
72             ItemId::Auto { for_: id, .. }
73             | ItemId::Blanket { for_: id, .. }
74             | ItemId::DefId(id) => id.is_local(),
75             ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
76         }
77     }
78 
79     #[inline]
80     #[track_caller]
expect_def_id(self) -> DefId81     crate fn expect_def_id(self) -> DefId {
82         self.as_def_id()
83             .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
84     }
85 
86     #[inline]
as_def_id(self) -> Option<DefId>87     crate fn as_def_id(self) -> Option<DefId> {
88         match self {
89             ItemId::DefId(id) => Some(id),
90             _ => None,
91         }
92     }
93 
94     #[inline]
krate(self) -> CrateNum95     crate fn krate(self) -> CrateNum {
96         match self {
97             ItemId::Auto { for_: id, .. }
98             | ItemId::Blanket { for_: id, .. }
99             | ItemId::DefId(id) => id.krate,
100             ItemId::Primitive(_, krate) => krate,
101         }
102     }
103 
104     #[inline]
index(self) -> Option<DefIndex>105     crate fn index(self) -> Option<DefIndex> {
106         match self {
107             ItemId::DefId(id) => Some(id.index),
108             _ => None,
109         }
110     }
111 }
112 
113 impl From<DefId> for ItemId {
from(id: DefId) -> Self114     fn from(id: DefId) -> Self {
115         Self::DefId(id)
116     }
117 }
118 
119 /// The crate currently being documented.
120 #[derive(Clone, Debug)]
121 crate struct Crate {
122     crate module: Item,
123     crate primitives: ThinVec<(DefId, PrimitiveType)>,
124     /// Only here so that they can be filtered through the rustdoc passes.
125     crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
126     crate collapsed: bool,
127 }
128 
129 // `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger.
130 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
131 rustc_data_structures::static_assert_size!(Crate, 80);
132 
133 impl Crate {
name(&self, tcx: TyCtxt<'_>) -> Symbol134     crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
135         ExternalCrate::LOCAL.name(tcx)
136     }
137 
src(&self, tcx: TyCtxt<'_>) -> FileName138     crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
139         ExternalCrate::LOCAL.src(tcx)
140     }
141 }
142 
143 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
144 #[derive(Clone, Debug)]
145 crate struct TraitWithExtraInfo {
146     crate trait_: Trait,
147     crate is_notable: bool,
148 }
149 
150 #[derive(Copy, Clone, Debug)]
151 crate struct ExternalCrate {
152     crate crate_num: CrateNum,
153 }
154 
155 impl ExternalCrate {
156     const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
157 
158     #[inline]
def_id(&self) -> DefId159     crate fn def_id(&self) -> DefId {
160         DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
161     }
162 
src(&self, tcx: TyCtxt<'_>) -> FileName163     crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
164         let krate_span = tcx.def_span(self.def_id());
165         tcx.sess.source_map().span_to_filename(krate_span)
166     }
167 
name(&self, tcx: TyCtxt<'_>) -> Symbol168     crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
169         tcx.crate_name(self.crate_num)
170     }
171 
src_root(&self, tcx: TyCtxt<'_>) -> PathBuf172     crate fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
173         match self.src(tcx) {
174             FileName::Real(ref p) => match p.local_path_if_available().parent() {
175                 Some(p) => p.to_path_buf(),
176                 None => PathBuf::new(),
177             },
178             _ => PathBuf::new(),
179         }
180     }
181 
182     /// Attempts to find where an external crate is located, given that we're
183     /// rendering in to the specified source destination.
location( &self, extern_url: Option<&str>, extern_url_takes_precedence: bool, dst: &std::path::Path, tcx: TyCtxt<'_>, ) -> ExternalLocation184     crate fn location(
185         &self,
186         extern_url: Option<&str>,
187         extern_url_takes_precedence: bool,
188         dst: &std::path::Path,
189         tcx: TyCtxt<'_>,
190     ) -> ExternalLocation {
191         use ExternalLocation::*;
192 
193         fn to_remote(url: impl ToString) -> ExternalLocation {
194             let mut url = url.to_string();
195             if !url.ends_with('/') {
196                 url.push('/');
197             }
198             Remote(url)
199         }
200 
201         // See if there's documentation generated into the local directory
202         // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
203         // Make sure to call `location()` by that time.
204         let local_location = dst.join(&*self.name(tcx).as_str());
205         if local_location.is_dir() {
206             return Local;
207         }
208 
209         if extern_url_takes_precedence {
210             if let Some(url) = extern_url {
211                 return to_remote(url);
212             }
213         }
214 
215         // Failing that, see if there's an attribute specifying where to find this
216         // external crate
217         let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
218         tcx.get_attrs(did)
219             .lists(sym::doc)
220             .filter(|a| a.has_name(sym::html_root_url))
221             .filter_map(|a| a.value_str())
222             .map(to_remote)
223             .next()
224             .or_else(|| extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
225             .unwrap_or(Unknown) // Well, at least we tried.
226     }
227 
keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)>228     crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
229         let root = self.def_id();
230 
231         let as_keyword = |res: Res<!>| {
232             if let Res::Def(DefKind::Mod, def_id) = res {
233                 let attrs = tcx.get_attrs(def_id);
234                 let mut keyword = None;
235                 for attr in attrs.lists(sym::doc) {
236                     if attr.has_name(sym::keyword) {
237                         if let Some(v) = attr.value_str() {
238                             keyword = Some(v);
239                             break;
240                         }
241                     }
242                 }
243                 return keyword.map(|p| (def_id, p));
244             }
245             None
246         };
247         if root.is_local() {
248             tcx.hir()
249                 .root_module()
250                 .item_ids
251                 .iter()
252                 .filter_map(|&id| {
253                     let item = tcx.hir().item(id);
254                     match item.kind {
255                         hir::ItemKind::Mod(_) => {
256                             as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
257                         }
258                         hir::ItemKind::Use(path, hir::UseKind::Single)
259                             if tcx.visibility(id.def_id).is_public() =>
260                         {
261                             as_keyword(path.res.expect_non_local())
262                                 .map(|(_, prim)| (id.def_id.to_def_id(), prim))
263                         }
264                         _ => None,
265                     }
266                 })
267                 .collect()
268         } else {
269             tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
270         }
271     }
272 
primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)>273     crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
274         let root = self.def_id();
275 
276         // Collect all inner modules which are tagged as implementations of
277         // primitives.
278         //
279         // Note that this loop only searches the top-level items of the crate,
280         // and this is intentional. If we were to search the entire crate for an
281         // item tagged with `#[doc(primitive)]` then we would also have to
282         // search the entirety of external modules for items tagged
283         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
284         // all that metadata unconditionally).
285         //
286         // In order to keep the metadata load under control, the
287         // `#[doc(primitive)]` feature is explicitly designed to only allow the
288         // primitive tags to show up as the top level items in a crate.
289         //
290         // Also note that this does not attempt to deal with modules tagged
291         // duplicately for the same primitive. This is handled later on when
292         // rendering by delegating everything to a hash map.
293         let as_primitive = |res: Res<!>| {
294             if let Res::Def(DefKind::Mod, def_id) = res {
295                 let attrs = tcx.get_attrs(def_id);
296                 let mut prim = None;
297                 for attr in attrs.lists(sym::doc) {
298                     if let Some(v) = attr.value_str() {
299                         if attr.has_name(sym::primitive) {
300                             prim = PrimitiveType::from_symbol(v);
301                             if prim.is_some() {
302                                 break;
303                             }
304                             // FIXME: should warn on unknown primitives?
305                         }
306                     }
307                 }
308                 return prim.map(|p| (def_id, p));
309             }
310             None
311         };
312 
313         if root.is_local() {
314             tcx.hir()
315                 .root_module()
316                 .item_ids
317                 .iter()
318                 .filter_map(|&id| {
319                     let item = tcx.hir().item(id);
320                     match item.kind {
321                         hir::ItemKind::Mod(_) => {
322                             as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
323                         }
324                         hir::ItemKind::Use(path, hir::UseKind::Single)
325                             if tcx.visibility(id.def_id).is_public() =>
326                         {
327                             as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
328                                 // Pretend the primitive is local.
329                                 (id.def_id.to_def_id(), prim)
330                             })
331                         }
332                         _ => None,
333                     }
334                 })
335                 .collect()
336         } else {
337             tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
338         }
339     }
340 }
341 
342 /// Anything with a source location and set of attributes and, optionally, a
343 /// name. That is, anything that can be documented. This doesn't correspond
344 /// directly to the AST's concept of an item; it's a strict superset.
345 #[derive(Clone, Debug)]
346 crate struct Item {
347     /// The name of this item.
348     /// Optional because not every item has a name, e.g. impls.
349     crate name: Option<Symbol>,
350     crate attrs: Box<Attributes>,
351     crate visibility: Visibility,
352     /// Information about this item that is specific to what kind of item it is.
353     /// E.g., struct vs enum vs function.
354     crate kind: Box<ItemKind>,
355     crate def_id: ItemId,
356 
357     crate cfg: Option<Arc<Cfg>>,
358 }
359 
360 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
361 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
362 rustc_data_structures::static_assert_size!(Item, 56);
363 
rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span364 crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
365     Span::new(def_id.as_local().map_or_else(
366         || tcx.def_span(def_id),
367         |local| {
368             let hir = tcx.hir();
369             hir.span_with_body(hir.local_def_id_to_hir_id(local))
370         },
371     ))
372 }
373 
374 impl Item {
stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability>375     crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
376         self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
377     }
378 
const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability>379     crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
380         self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
381     }
382 
deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation>383     crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
384         self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
385     }
386 
inner_docs(&self, tcx: TyCtxt<'_>) -> bool387     crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
388         self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
389     }
390 
span(&self, tcx: TyCtxt<'_>) -> Span391     crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
392         let kind = match &*self.kind {
393             ItemKind::StrippedItem(k) => k,
394             _ => &*self.kind,
395         };
396         match kind {
397             ItemKind::ModuleItem(Module { span, .. }) => *span,
398             ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
399             ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
400                 if let ItemId::Blanket { impl_id, .. } = self.def_id {
401                     rustc_span(impl_id, tcx)
402                 } else {
403                     panic!("blanket impl item has non-blanket ID")
404                 }
405             }
406             _ => {
407                 self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
408             }
409         }
410     }
411 
attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span412     crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
413         crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
414     }
415 
416     /// Finds the `doc` attribute as a NameValue and returns the corresponding
417     /// value found.
doc_value(&self) -> Option<String>418     crate fn doc_value(&self) -> Option<String> {
419         self.attrs.doc_value()
420     }
421 
422     /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
423     /// `hir_id` to a [`DefId`]
from_hir_id_and_parts( hir_id: hir::HirId, name: Option<Symbol>, kind: ItemKind, cx: &mut DocContext<'_>, ) -> Item424     pub fn from_hir_id_and_parts(
425         hir_id: hir::HirId,
426         name: Option<Symbol>,
427         kind: ItemKind,
428         cx: &mut DocContext<'_>,
429     ) -> Item {
430         Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
431     }
432 
from_def_id_and_parts( def_id: DefId, name: Option<Symbol>, kind: ItemKind, cx: &mut DocContext<'_>, ) -> Item433     pub fn from_def_id_and_parts(
434         def_id: DefId,
435         name: Option<Symbol>,
436         kind: ItemKind,
437         cx: &mut DocContext<'_>,
438     ) -> Item {
439         let ast_attrs = cx.tcx.get_attrs(def_id);
440 
441         Self::from_def_id_and_attrs_and_parts(
442             def_id,
443             name,
444             kind,
445             box ast_attrs.clean(cx),
446             cx,
447             ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
448         )
449     }
450 
from_def_id_and_attrs_and_parts( def_id: DefId, name: Option<Symbol>, kind: ItemKind, attrs: Box<Attributes>, cx: &mut DocContext<'_>, cfg: Option<Arc<Cfg>>, ) -> Item451     pub fn from_def_id_and_attrs_and_parts(
452         def_id: DefId,
453         name: Option<Symbol>,
454         kind: ItemKind,
455         attrs: Box<Attributes>,
456         cx: &mut DocContext<'_>,
457         cfg: Option<Arc<Cfg>>,
458     ) -> Item {
459         trace!("name={:?}, def_id={:?}", name, def_id);
460 
461         Item {
462             def_id: def_id.into(),
463             kind: box kind,
464             name,
465             attrs,
466             visibility: cx.tcx.visibility(def_id).clean(cx),
467             cfg,
468         }
469     }
470 
471     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
472     /// with newlines.
collapsed_doc_value(&self) -> Option<String>473     crate fn collapsed_doc_value(&self) -> Option<String> {
474         self.attrs.collapsed_doc_value()
475     }
476 
links(&self, cx: &Context<'_>) -> Vec<RenderedLink>477     crate fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
478         use crate::html::format::href;
479 
480         cx.cache()
481             .intra_doc_links
482             .get(&self.def_id)
483             .map_or(&[][..], |v| v.as_slice())
484             .iter()
485             .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
486                 debug!(?did);
487                 if let Ok((mut href, ..)) = href(*did, cx) {
488                     debug!(?href);
489                     if let Some(ref fragment) = *fragment {
490                         href.push('#');
491                         href.push_str(fragment);
492                     }
493                     Some(RenderedLink {
494                         original_text: s.clone(),
495                         new_text: link_text.clone(),
496                         href,
497                     })
498                 } else {
499                     None
500                 }
501             })
502             .collect()
503     }
504 
505     /// Find a list of all link names, without finding their href.
506     ///
507     /// This is used for generating summary text, which does not include
508     /// the link text, but does need to know which `[]`-bracketed names
509     /// are actually links.
link_names(&self, cache: &Cache) -> Vec<RenderedLink>510     crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
511         cache
512             .intra_doc_links
513             .get(&self.def_id)
514             .map_or(&[][..], |v| v.as_slice())
515             .iter()
516             .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
517                 original_text: s.clone(),
518                 new_text: link_text.clone(),
519                 href: String::new(),
520             })
521             .collect()
522     }
523 
is_crate(&self) -> bool524     crate fn is_crate(&self) -> bool {
525         self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
526     }
is_mod(&self) -> bool527     crate fn is_mod(&self) -> bool {
528         self.type_() == ItemType::Module
529     }
is_trait(&self) -> bool530     crate fn is_trait(&self) -> bool {
531         self.type_() == ItemType::Trait
532     }
is_struct(&self) -> bool533     crate fn is_struct(&self) -> bool {
534         self.type_() == ItemType::Struct
535     }
is_enum(&self) -> bool536     crate fn is_enum(&self) -> bool {
537         self.type_() == ItemType::Enum
538     }
is_variant(&self) -> bool539     crate fn is_variant(&self) -> bool {
540         self.type_() == ItemType::Variant
541     }
is_associated_type(&self) -> bool542     crate fn is_associated_type(&self) -> bool {
543         self.type_() == ItemType::AssocType
544     }
is_associated_const(&self) -> bool545     crate fn is_associated_const(&self) -> bool {
546         self.type_() == ItemType::AssocConst
547     }
is_method(&self) -> bool548     crate fn is_method(&self) -> bool {
549         self.type_() == ItemType::Method
550     }
is_ty_method(&self) -> bool551     crate fn is_ty_method(&self) -> bool {
552         self.type_() == ItemType::TyMethod
553     }
is_typedef(&self) -> bool554     crate fn is_typedef(&self) -> bool {
555         self.type_() == ItemType::Typedef
556     }
is_primitive(&self) -> bool557     crate fn is_primitive(&self) -> bool {
558         self.type_() == ItemType::Primitive
559     }
is_union(&self) -> bool560     crate fn is_union(&self) -> bool {
561         self.type_() == ItemType::Union
562     }
is_import(&self) -> bool563     crate fn is_import(&self) -> bool {
564         self.type_() == ItemType::Import
565     }
is_extern_crate(&self) -> bool566     crate fn is_extern_crate(&self) -> bool {
567         self.type_() == ItemType::ExternCrate
568     }
is_keyword(&self) -> bool569     crate fn is_keyword(&self) -> bool {
570         self.type_() == ItemType::Keyword
571     }
is_stripped(&self) -> bool572     crate fn is_stripped(&self) -> bool {
573         match *self.kind {
574             StrippedItem(..) => true,
575             ImportItem(ref i) => !i.should_be_displayed,
576             _ => false,
577         }
578     }
has_stripped_fields(&self) -> Option<bool>579     crate fn has_stripped_fields(&self) -> Option<bool> {
580         match *self.kind {
581             StructItem(ref _struct) => Some(_struct.fields_stripped),
582             UnionItem(ref union) => Some(union.fields_stripped),
583             VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
584             _ => None,
585         }
586     }
587 
stability_class(&self, tcx: TyCtxt<'_>) -> Option<String>588     crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
589         self.stability(tcx).as_ref().and_then(|s| {
590             let mut classes = Vec::with_capacity(2);
591 
592             if s.level.is_unstable() {
593                 classes.push("unstable");
594             }
595 
596             // FIXME: what about non-staged API items that are deprecated?
597             if self.deprecation(tcx).is_some() {
598                 classes.push("deprecated");
599             }
600 
601             if !classes.is_empty() { Some(classes.join(" ")) } else { None }
602         })
603     }
604 
stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr>605     crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
606         match self.stability(tcx)?.level {
607             StabilityLevel::Stable { since, .. } => Some(since.as_str()),
608             StabilityLevel::Unstable { .. } => None,
609         }
610     }
611 
const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr>612     crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
613         match self.const_stability(tcx)?.level {
614             StabilityLevel::Stable { since, .. } => Some(since.as_str()),
615             StabilityLevel::Unstable { .. } => None,
616         }
617     }
618 
is_non_exhaustive(&self) -> bool619     crate fn is_non_exhaustive(&self) -> bool {
620         self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
621     }
622 
623     /// Returns a documentation-level item type from the item.
type_(&self) -> ItemType624     crate fn type_(&self) -> ItemType {
625         ItemType::from(self)
626     }
627 
is_default(&self) -> bool628     crate fn is_default(&self) -> bool {
629         match *self.kind {
630             ItemKind::MethodItem(_, Some(defaultness)) => {
631                 defaultness.has_value() && !defaultness.is_final()
632             }
633             _ => false,
634         }
635     }
636 }
637 
638 #[derive(Clone, Debug)]
639 crate enum ItemKind {
640     ExternCrateItem {
641         /// The crate's name, *not* the name it's imported as.
642         src: Option<Symbol>,
643     },
644     ImportItem(Import),
645     StructItem(Struct),
646     UnionItem(Union),
647     EnumItem(Enum),
648     FunctionItem(Function),
649     ModuleItem(Module),
650     TypedefItem(Typedef, bool /* is associated type */),
651     OpaqueTyItem(OpaqueTy),
652     StaticItem(Static),
653     ConstantItem(Constant),
654     TraitItem(Trait),
655     TraitAliasItem(TraitAlias),
656     ImplItem(Impl),
657     /// A method signature only. Used for required methods in traits (ie,
658     /// non-default-methods).
659     TyMethodItem(Function),
660     /// A method with a body.
661     MethodItem(Function, Option<hir::Defaultness>),
662     StructFieldItem(Type),
663     VariantItem(Variant),
664     /// `fn`s from an extern block
665     ForeignFunctionItem(Function),
666     /// `static`s from an extern block
667     ForeignStaticItem(Static),
668     /// `type`s from an extern block
669     ForeignTypeItem,
670     MacroItem(Macro),
671     ProcMacroItem(ProcMacro),
672     PrimitiveItem(PrimitiveType),
673     AssocConstItem(Type, Option<String>),
674     /// An associated item in a trait or trait impl.
675     ///
676     /// The bounds may be non-empty if there is a `where` clause.
677     /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
678     AssocTypeItem(Vec<GenericBound>, Option<Type>),
679     /// An item that has been stripped by a rustdoc pass
680     StrippedItem(Box<ItemKind>),
681     KeywordItem(Symbol),
682 }
683 
684 impl ItemKind {
685     /// Some items contain others such as structs (for their fields) and Enums
686     /// (for their variants). This method returns those contained items.
inner_items(&self) -> impl Iterator<Item = &Item>687     crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
688         match self {
689             StructItem(s) => s.fields.iter(),
690             UnionItem(u) => u.fields.iter(),
691             VariantItem(Variant::Struct(v)) => v.fields.iter(),
692             VariantItem(Variant::Tuple(v)) => v.iter(),
693             EnumItem(e) => e.variants.iter(),
694             TraitItem(t) => t.items.iter(),
695             ImplItem(i) => i.items.iter(),
696             ModuleItem(m) => m.items.iter(),
697             ExternCrateItem { .. }
698             | ImportItem(_)
699             | FunctionItem(_)
700             | TypedefItem(_, _)
701             | OpaqueTyItem(_)
702             | StaticItem(_)
703             | ConstantItem(_)
704             | TraitAliasItem(_)
705             | TyMethodItem(_)
706             | MethodItem(_, _)
707             | StructFieldItem(_)
708             | VariantItem(_)
709             | ForeignFunctionItem(_)
710             | ForeignStaticItem(_)
711             | ForeignTypeItem
712             | MacroItem(_)
713             | ProcMacroItem(_)
714             | PrimitiveItem(_)
715             | AssocConstItem(_, _)
716             | AssocTypeItem(_, _)
717             | StrippedItem(_)
718             | KeywordItem(_) => [].iter(),
719         }
720     }
721 }
722 
723 #[derive(Clone, Debug)]
724 crate struct Module {
725     crate items: Vec<Item>,
726     crate span: Span,
727 }
728 
729 crate struct ListAttributesIter<'a> {
730     attrs: slice::Iter<'a, ast::Attribute>,
731     current_list: vec::IntoIter<ast::NestedMetaItem>,
732     name: Symbol,
733 }
734 
735 impl<'a> Iterator for ListAttributesIter<'a> {
736     type Item = ast::NestedMetaItem;
737 
next(&mut self) -> Option<Self::Item>738     fn next(&mut self) -> Option<Self::Item> {
739         if let Some(nested) = self.current_list.next() {
740             return Some(nested);
741         }
742 
743         for attr in &mut self.attrs {
744             if let Some(list) = attr.meta_item_list() {
745                 if attr.has_name(self.name) {
746                     self.current_list = list.into_iter();
747                     if let Some(nested) = self.current_list.next() {
748                         return Some(nested);
749                     }
750                 }
751             }
752         }
753 
754         None
755     }
756 
size_hint(&self) -> (usize, Option<usize>)757     fn size_hint(&self) -> (usize, Option<usize>) {
758         let lower = self.current_list.len();
759         (lower, None)
760     }
761 }
762 
763 crate trait AttributesExt {
764     /// Finds an attribute as List and returns the list of attributes nested inside.
lists(&self, name: Symbol) -> ListAttributesIter<'_>765     fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
766 
span(&self) -> Option<rustc_span::Span>767     fn span(&self) -> Option<rustc_span::Span>;
768 
inner_docs(&self) -> bool769     fn inner_docs(&self) -> bool;
770 
other_attrs(&self) -> Vec<ast::Attribute>771     fn other_attrs(&self) -> Vec<ast::Attribute>;
772 
cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>773     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
774 }
775 
776 impl AttributesExt for [ast::Attribute] {
lists(&self, name: Symbol) -> ListAttributesIter<'_>777     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
778         ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
779     }
780 
781     /// Return the span of the first doc-comment, if it exists.
span(&self) -> Option<rustc_span::Span>782     fn span(&self) -> Option<rustc_span::Span> {
783         self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
784     }
785 
786     /// Returns whether the first doc-comment is an inner attribute.
787     ///
788     //// If there are no doc-comments, return true.
789     /// FIXME(#78591): Support both inner and outer attributes on the same item.
inner_docs(&self) -> bool790     fn inner_docs(&self) -> bool {
791         self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
792     }
793 
other_attrs(&self) -> Vec<ast::Attribute>794     fn other_attrs(&self) -> Vec<ast::Attribute> {
795         self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
796     }
797 
cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>798     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
799         let sess = tcx.sess;
800         let doc_cfg_active = tcx.features().doc_cfg;
801         let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
802 
803         fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
804             let mut iter = it.into_iter();
805             let item = iter.next()?;
806             if iter.next().is_some() {
807                 return None;
808             }
809             Some(item)
810         }
811 
812         let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
813             let mut doc_cfg = self
814                 .iter()
815                 .filter(|attr| attr.has_name(sym::doc))
816                 .flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
817                 .filter(|attr| attr.has_name(sym::cfg))
818                 .peekable();
819             if doc_cfg.peek().is_some() && doc_cfg_active {
820                 doc_cfg
821                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
822                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
823             } else if doc_auto_cfg_active {
824                 self.iter()
825                     .filter(|attr| attr.has_name(sym::cfg))
826                     .filter_map(|attr| single(attr.meta_item_list()?))
827                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
828                     .filter(|cfg| !hidden_cfg.contains(cfg))
829                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
830             } else {
831                 Cfg::True
832             }
833         } else {
834             Cfg::True
835         };
836 
837         for attr in self.iter() {
838             // #[doc]
839             if attr.doc_str().is_none() && attr.has_name(sym::doc) {
840                 // #[doc(...)]
841                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
842                     for item in list {
843                         // #[doc(hidden)]
844                         if !item.has_name(sym::cfg) {
845                             continue;
846                         }
847                         // #[doc(cfg(...))]
848                         if let Some(cfg_mi) = item
849                             .meta_item()
850                             .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
851                         {
852                             match Cfg::parse(cfg_mi) {
853                                 Ok(new_cfg) => cfg &= new_cfg,
854                                 Err(e) => sess.span_err(e.span, e.msg),
855                             }
856                         }
857                     }
858                 }
859             }
860         }
861 
862         // treat #[target_feature(enable = "feat")] attributes as if they were
863         // #[doc(cfg(target_feature = "feat"))] attributes as well
864         for attr in self.lists(sym::target_feature) {
865             if attr.has_name(sym::enable) {
866                 if let Some(feat) = attr.value_str() {
867                     let meta = attr::mk_name_value_item_str(
868                         Ident::with_dummy_span(sym::target_feature),
869                         feat,
870                         DUMMY_SP,
871                     );
872                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
873                         cfg &= feat_cfg;
874                     }
875                 }
876             }
877         }
878 
879         if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
880     }
881 }
882 
883 crate trait NestedAttributesExt {
884     /// Returns `true` if the attribute list contains a specific `Word`
has_word(self, word: Symbol) -> bool885     fn has_word(self, word: Symbol) -> bool;
get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>886     fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
887 }
888 
889 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
890     NestedAttributesExt for I
891 {
has_word(self, word: Symbol) -> bool892     fn has_word(self, word: Symbol) -> bool {
893         self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
894     }
895 
get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem>896     fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
897         self.find(|attr| attr.is_word() && attr.has_name(word))
898     }
899 }
900 
901 /// A portion of documentation, extracted from a `#[doc]` attribute.
902 ///
903 /// Each variant contains the line number within the complete doc-comment where the fragment
904 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
905 ///
906 /// Included files are kept separate from inline doc comments so that proper line-number
907 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
908 /// kept separate because of issue #42760.
909 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
910 crate struct DocFragment {
911     crate span: rustc_span::Span,
912     /// The module this doc-comment came from.
913     ///
914     /// This allows distinguishing between the original documentation and a pub re-export.
915     /// If it is `None`, the item was not re-exported.
916     crate parent_module: Option<DefId>,
917     crate doc: Symbol,
918     crate kind: DocFragmentKind,
919     crate need_backline: bool,
920     crate indent: usize,
921 }
922 
923 // `DocFragment` is used a lot. Make sure it doesn't unintentionally get bigger.
924 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
925 rustc_data_structures::static_assert_size!(DocFragment, 32);
926 
927 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
928 crate enum DocFragmentKind {
929     /// A doc fragment created from a `///` or `//!` doc comment.
930     SugaredDoc,
931     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
932     RawDoc,
933 }
934 
935 // The goal of this function is to apply the `DocFragment` transformations that are required when
936 // transforming into the final markdown. So the transformations in here are:
937 //
938 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
939 //   multiple lines in case of `#[doc = ""]`).
940 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
941 //   `need_backline` field).
add_doc_fragment(out: &mut String, frag: &DocFragment)942 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
943     let s = frag.doc.as_str();
944     let mut iter = s.lines().peekable();
945     while let Some(line) = iter.next() {
946         if line.chars().any(|c| !c.is_whitespace()) {
947             assert!(line.len() >= frag.indent);
948             out.push_str(&line[frag.indent..]);
949         } else {
950             out.push_str(line);
951         }
952         if iter.peek().is_some() {
953             out.push('\n');
954         }
955     }
956     if frag.need_backline {
957         out.push('\n');
958     }
959 }
960 
961 impl<'a> FromIterator<&'a DocFragment> for String {
from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = &'a DocFragment>,962     fn from_iter<T>(iter: T) -> Self
963     where
964         T: IntoIterator<Item = &'a DocFragment>,
965     {
966         iter.into_iter().fold(String::new(), |mut acc, frag| {
967             add_doc_fragment(&mut acc, frag);
968             acc
969         })
970     }
971 }
972 
973 /// A link that has not yet been rendered.
974 ///
975 /// This link will be turned into a rendered link by [`Item::links`].
976 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
977 crate struct ItemLink {
978     /// The original link written in the markdown
979     pub(crate) link: String,
980     /// The link text displayed in the HTML.
981     ///
982     /// This may not be the same as `link` if there was a disambiguator
983     /// in an intra-doc link (e.g. \[`fn@f`\])
984     pub(crate) link_text: String,
985     pub(crate) did: DefId,
986     /// The url fragment to append to the link
987     pub(crate) fragment: Option<String>,
988 }
989 
990 pub struct RenderedLink {
991     /// The text the link was original written as.
992     ///
993     /// This could potentially include disambiguators and backticks.
994     pub(crate) original_text: String,
995     /// The text to display in the HTML
996     pub(crate) new_text: String,
997     /// The URL to put in the `href`
998     pub(crate) href: String,
999 }
1000 
1001 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1002 /// as well as doc comments.
1003 #[derive(Clone, Debug, Default)]
1004 crate struct Attributes {
1005     crate doc_strings: Vec<DocFragment>,
1006     crate other_attrs: Vec<ast::Attribute>,
1007 }
1008 
1009 impl Attributes {
lists(&self, name: Symbol) -> ListAttributesIter<'_>1010     crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
1011         self.other_attrs.lists(name)
1012     }
1013 
has_doc_flag(&self, flag: Symbol) -> bool1014     crate fn has_doc_flag(&self, flag: Symbol) -> bool {
1015         for attr in &self.other_attrs {
1016             if !attr.has_name(sym::doc) {
1017                 continue;
1018             }
1019 
1020             if let Some(items) = attr.meta_item_list() {
1021                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
1022                     return true;
1023                 }
1024             }
1025         }
1026 
1027         false
1028     }
1029 
from_ast( attrs: &[ast::Attribute], additional_attrs: Option<(&[ast::Attribute], DefId)>, ) -> Attributes1030     crate fn from_ast(
1031         attrs: &[ast::Attribute],
1032         additional_attrs: Option<(&[ast::Attribute], DefId)>,
1033     ) -> Attributes {
1034         let mut doc_strings: Vec<DocFragment> = vec![];
1035 
1036         fn update_need_backline(doc_strings: &mut Vec<DocFragment>) {
1037             if let Some(prev) = doc_strings.last_mut() {
1038                 prev.need_backline = true;
1039             }
1040         }
1041 
1042         let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
1043             if let Some(value) = attr.doc_str() {
1044                 trace!("got doc_str={:?}", value);
1045                 let value = beautify_doc_string(value);
1046                 let kind = if attr.is_doc_comment() {
1047                     DocFragmentKind::SugaredDoc
1048                 } else {
1049                     DocFragmentKind::RawDoc
1050                 };
1051 
1052                 let frag = DocFragment {
1053                     span: attr.span,
1054                     doc: value,
1055                     kind,
1056                     parent_module,
1057                     need_backline: false,
1058                     indent: 0,
1059                 };
1060 
1061                 update_need_backline(&mut doc_strings);
1062 
1063                 doc_strings.push(frag);
1064 
1065                 None
1066             } else {
1067                 Some(attr.clone())
1068             }
1069         };
1070 
1071         // Additional documentation should be shown before the original documentation
1072         let other_attrs = additional_attrs
1073             .into_iter()
1074             .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
1075             .flatten()
1076             .chain(attrs.iter().map(|attr| (attr, None)))
1077             .filter_map(clean_attr)
1078             .collect();
1079 
1080         Attributes { doc_strings, other_attrs }
1081     }
1082 
1083     /// Finds the `doc` attribute as a NameValue and returns the corresponding
1084     /// value found.
doc_value(&self) -> Option<String>1085     crate fn doc_value(&self) -> Option<String> {
1086         let mut iter = self.doc_strings.iter();
1087 
1088         let ori = iter.next()?;
1089         let mut out = String::new();
1090         add_doc_fragment(&mut out, ori);
1091         for new_frag in iter {
1092             if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module {
1093                 break;
1094             }
1095             add_doc_fragment(&mut out, new_frag);
1096         }
1097         if out.is_empty() { None } else { Some(out) }
1098     }
1099 
1100     /// Return the doc-comments on this item, grouped by the module they came from.
1101     ///
1102     /// The module can be different if this is a re-export with added documentation.
collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String>1103     crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
1104         let mut ret = FxHashMap::default();
1105 
1106         for new_frag in self.doc_strings.iter() {
1107             let out = ret.entry(new_frag.parent_module).or_default();
1108             add_doc_fragment(out, new_frag);
1109         }
1110         ret
1111     }
1112 
1113     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1114     /// with newlines.
collapsed_doc_value(&self) -> Option<String>1115     crate fn collapsed_doc_value(&self) -> Option<String> {
1116         if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
1117     }
1118 
get_doc_aliases(&self) -> Box<[Symbol]>1119     crate fn get_doc_aliases(&self) -> Box<[Symbol]> {
1120         let mut aliases = FxHashSet::default();
1121 
1122         for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1123             if let Some(values) = attr.meta_item_list() {
1124                 for l in values {
1125                     match l.literal().unwrap().kind {
1126                         ast::LitKind::Str(s, _) => {
1127                             aliases.insert(s);
1128                         }
1129                         _ => unreachable!(),
1130                     }
1131                 }
1132             } else {
1133                 aliases.insert(attr.value_str().unwrap());
1134             }
1135         }
1136         aliases.into_iter().collect::<Vec<_>>().into()
1137     }
1138 }
1139 
1140 impl PartialEq for Attributes {
eq(&self, rhs: &Self) -> bool1141     fn eq(&self, rhs: &Self) -> bool {
1142         self.doc_strings == rhs.doc_strings
1143             && self
1144                 .other_attrs
1145                 .iter()
1146                 .map(|attr| attr.id)
1147                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1148     }
1149 }
1150 
1151 impl Eq for Attributes {}
1152 
1153 impl Hash for Attributes {
hash<H: Hasher>(&self, hasher: &mut H)1154     fn hash<H: Hasher>(&self, hasher: &mut H) {
1155         self.doc_strings.hash(hasher);
1156         for attr in &self.other_attrs {
1157             attr.id.hash(hasher);
1158         }
1159     }
1160 }
1161 
1162 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1163 crate enum GenericBound {
1164     TraitBound(PolyTrait, hir::TraitBoundModifier),
1165     Outlives(Lifetime),
1166 }
1167 
1168 impl GenericBound {
maybe_sized(cx: &mut DocContext<'_>) -> GenericBound1169     crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1170         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1171         let empty = cx.tcx.intern_substs(&[]);
1172         let path = external_path(cx, did, false, vec![], empty);
1173         inline::record_extern_fqn(cx, did, ItemType::Trait);
1174         GenericBound::TraitBound(
1175             PolyTrait { trait_: path, generic_params: Vec::new() },
1176             hir::TraitBoundModifier::Maybe,
1177         )
1178     }
1179 
is_sized_bound(&self, cx: &DocContext<'_>) -> bool1180     crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1181         use rustc_hir::TraitBoundModifier as TBM;
1182         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1183             if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() {
1184                 return true;
1185             }
1186         }
1187         false
1188     }
1189 
get_poly_trait(&self) -> Option<PolyTrait>1190     crate fn get_poly_trait(&self) -> Option<PolyTrait> {
1191         if let GenericBound::TraitBound(ref p, _) = *self {
1192             return Some(p.clone());
1193         }
1194         None
1195     }
1196 
get_trait_path(&self) -> Option<Path>1197     crate fn get_trait_path(&self) -> Option<Path> {
1198         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1199             Some(trait_.clone())
1200         } else {
1201             None
1202         }
1203     }
1204 }
1205 
1206 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1207 crate struct Lifetime(pub Symbol);
1208 
1209 impl Lifetime {
get_ref(&self) -> SymbolStr1210     crate fn get_ref(&self) -> SymbolStr {
1211         self.0.as_str()
1212     }
1213 
statik() -> Lifetime1214     crate fn statik() -> Lifetime {
1215         Lifetime(kw::StaticLifetime)
1216     }
1217 
elided() -> Lifetime1218     crate fn elided() -> Lifetime {
1219         Lifetime(kw::UnderscoreLifetime)
1220     }
1221 }
1222 
1223 #[derive(Clone, Debug)]
1224 crate enum WherePredicate {
1225     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
1226     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1227     EqPredicate { lhs: Type, rhs: Type },
1228 }
1229 
1230 impl WherePredicate {
get_bounds(&self) -> Option<&[GenericBound]>1231     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1232         match *self {
1233             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1234             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1235             _ => None,
1236         }
1237     }
1238 }
1239 
1240 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1241 crate enum GenericParamDefKind {
1242     Lifetime { outlives: Vec<Lifetime> },
1243     Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1244     Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
1245 }
1246 
1247 impl GenericParamDefKind {
is_type(&self) -> bool1248     crate fn is_type(&self) -> bool {
1249         matches!(self, GenericParamDefKind::Type { .. })
1250     }
1251 
1252     // FIXME(eddyb) this either returns the default of a type parameter, or the
1253     // type of a `const` parameter. It seems that the intention is to *visit*
1254     // any embedded types, but `get_type` seems to be the wrong name for that.
get_type(&self) -> Option<Type>1255     crate fn get_type(&self) -> Option<Type> {
1256         match self {
1257             GenericParamDefKind::Type { default, .. } => default.as_deref().cloned(),
1258             GenericParamDefKind::Const { ty, .. } => Some((&**ty).clone()),
1259             GenericParamDefKind::Lifetime { .. } => None,
1260         }
1261     }
1262 }
1263 
1264 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1265 crate struct GenericParamDef {
1266     crate name: Symbol,
1267     crate kind: GenericParamDefKind,
1268 }
1269 
1270 // `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger.
1271 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1272 rustc_data_structures::static_assert_size!(GenericParamDef, 56);
1273 
1274 impl GenericParamDef {
is_synthetic_type_param(&self) -> bool1275     crate fn is_synthetic_type_param(&self) -> bool {
1276         match self.kind {
1277             GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1278             GenericParamDefKind::Type { synthetic, .. } => synthetic,
1279         }
1280     }
1281 
is_type(&self) -> bool1282     crate fn is_type(&self) -> bool {
1283         self.kind.is_type()
1284     }
1285 
get_type(&self) -> Option<Type>1286     crate fn get_type(&self) -> Option<Type> {
1287         self.kind.get_type()
1288     }
1289 
get_bounds(&self) -> Option<&[GenericBound]>1290     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1291         match self.kind {
1292             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1293             _ => None,
1294         }
1295     }
1296 }
1297 
1298 // maybe use a Generic enum and use Vec<Generic>?
1299 #[derive(Clone, Debug, Default)]
1300 crate struct Generics {
1301     crate params: Vec<GenericParamDef>,
1302     crate where_predicates: Vec<WherePredicate>,
1303 }
1304 
1305 #[derive(Clone, Debug)]
1306 crate struct Function {
1307     crate decl: FnDecl,
1308     crate generics: Generics,
1309     crate header: hir::FnHeader,
1310 }
1311 
1312 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1313 crate struct FnDecl {
1314     crate inputs: Arguments,
1315     crate output: FnRetTy,
1316     crate c_variadic: bool,
1317 }
1318 
1319 impl FnDecl {
self_type(&self) -> Option<SelfTy>1320     crate fn self_type(&self) -> Option<SelfTy> {
1321         self.inputs.values.get(0).and_then(|v| v.to_self())
1322     }
1323 
1324     /// Returns the sugared return type for an async function.
1325     ///
1326     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1327     /// will return `i32`.
1328     ///
1329     /// # Panics
1330     ///
1331     /// This function will panic if the return type does not match the expected sugaring for async
1332     /// functions.
sugared_async_return_type(&self) -> FnRetTy1333     crate fn sugared_async_return_type(&self) -> FnRetTy {
1334         match &self.output {
1335             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1336                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1337                     let bindings = trait_.bindings().unwrap();
1338                     FnRetTy::Return(bindings[0].ty().clone())
1339                 }
1340                 _ => panic!("unexpected desugaring of async function"),
1341             },
1342             _ => panic!("unexpected desugaring of async function"),
1343         }
1344     }
1345 }
1346 
1347 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1348 crate struct Arguments {
1349     crate values: Vec<Argument>,
1350 }
1351 
1352 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1353 crate struct Argument {
1354     crate type_: Type,
1355     crate name: Symbol,
1356 }
1357 
1358 #[derive(Clone, PartialEq, Debug)]
1359 crate enum SelfTy {
1360     SelfValue,
1361     SelfBorrowed(Option<Lifetime>, Mutability),
1362     SelfExplicit(Type),
1363 }
1364 
1365 impl Argument {
to_self(&self) -> Option<SelfTy>1366     crate fn to_self(&self) -> Option<SelfTy> {
1367         if self.name != kw::SelfLower {
1368             return None;
1369         }
1370         if self.type_.is_self_type() {
1371             return Some(SelfValue);
1372         }
1373         match self.type_ {
1374             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1375                 Some(SelfBorrowed(lifetime.clone(), mutability))
1376             }
1377             _ => Some(SelfExplicit(self.type_.clone())),
1378         }
1379     }
1380 }
1381 
1382 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1383 crate enum FnRetTy {
1384     Return(Type),
1385     DefaultReturn,
1386 }
1387 
1388 impl FnRetTy {
as_return(&self) -> Option<&Type>1389     crate fn as_return(&self) -> Option<&Type> {
1390         match self {
1391             Return(ret) => Some(ret),
1392             DefaultReturn => None,
1393         }
1394     }
1395 }
1396 
1397 #[derive(Clone, Debug)]
1398 crate struct Trait {
1399     crate unsafety: hir::Unsafety,
1400     crate items: Vec<Item>,
1401     crate generics: Generics,
1402     crate bounds: Vec<GenericBound>,
1403     crate is_auto: bool,
1404 }
1405 
1406 #[derive(Clone, Debug)]
1407 crate struct TraitAlias {
1408     crate generics: Generics,
1409     crate bounds: Vec<GenericBound>,
1410 }
1411 
1412 /// A trait reference, which may have higher ranked lifetimes.
1413 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1414 crate struct PolyTrait {
1415     crate trait_: Path,
1416     crate generic_params: Vec<GenericParamDef>,
1417 }
1418 
1419 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1420 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1421 crate enum Type {
1422     /// A named type, which could be a trait.
1423     ///
1424     /// This is mostly Rustdoc's version of [`hir::Path`].
1425     /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1426     Path { path: Path },
1427     /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1428     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1429     /// A type parameter.
1430     Generic(Symbol),
1431     /// A primitive (aka, builtin) type.
1432     Primitive(PrimitiveType),
1433     /// A function pointer: `extern "ABI" fn(...) -> ...`
1434     BareFunction(Box<BareFunctionDecl>),
1435     /// A tuple type: `(i32, &str)`.
1436     Tuple(Vec<Type>),
1437     /// A slice type (does *not* include the `&`): `[i32]`
1438     Slice(Box<Type>),
1439     /// An array type.
1440     ///
1441     /// The `String` field is a stringified version of the array's length parameter.
1442     Array(Box<Type>, String),
1443     /// A raw pointer type: `*const i32`, `*mut i32`
1444     RawPointer(Mutability, Box<Type>),
1445     /// A reference type: `&i32`, `&'a mut Foo`
1446     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
1447 
1448     /// A qualified path to an associated item: `<Type as Trait>::Name`
1449     QPath {
1450         name: Symbol,
1451         self_type: Box<Type>,
1452         /// FIXME: This is a hack that should be removed; see [this discussion][1].
1453         ///
1454         /// [1]: https://github.com/rust-lang/rust/pull/85479#discussion_r635729093
1455         self_def_id: Option<DefId>,
1456         trait_: Path,
1457     },
1458 
1459     /// A type that is inferred: `_`
1460     Infer,
1461 
1462     /// An `impl Trait`: `impl TraitA + TraitB + ...`
1463     ImplTrait(Vec<GenericBound>),
1464 }
1465 
1466 // `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
1467 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1468 rustc_data_structures::static_assert_size!(Type, 72);
1469 
1470 impl Type {
primitive_type(&self) -> Option<PrimitiveType>1471     crate fn primitive_type(&self) -> Option<PrimitiveType> {
1472         match *self {
1473             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1474             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1475             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1476             Tuple(ref tys) => {
1477                 if tys.is_empty() {
1478                     Some(PrimitiveType::Unit)
1479                 } else {
1480                     Some(PrimitiveType::Tuple)
1481                 }
1482             }
1483             RawPointer(..) => Some(PrimitiveType::RawPointer),
1484             BareFunction(..) => Some(PrimitiveType::Fn),
1485             _ => None,
1486         }
1487     }
1488 
1489     /// Checks if this is a `T::Name` path for an associated type.
is_assoc_ty(&self) -> bool1490     crate fn is_assoc_ty(&self) -> bool {
1491         match self {
1492             Type::Path { path, .. } => path.is_assoc_ty(),
1493             _ => false,
1494         }
1495     }
1496 
is_self_type(&self) -> bool1497     crate fn is_self_type(&self) -> bool {
1498         match *self {
1499             Generic(name) => name == kw::SelfUpper,
1500             _ => false,
1501         }
1502     }
1503 
generics(&self) -> Option<Vec<&Type>>1504     crate fn generics(&self) -> Option<Vec<&Type>> {
1505         match self {
1506             Type::Path { path, .. } => path.generics(),
1507             _ => None,
1508         }
1509     }
1510 
is_full_generic(&self) -> bool1511     crate fn is_full_generic(&self) -> bool {
1512         matches!(self, Type::Generic(_))
1513     }
1514 
is_primitive(&self) -> bool1515     crate fn is_primitive(&self) -> bool {
1516         self.primitive_type().is_some()
1517     }
1518 
projection(&self) -> Option<(&Type, DefId, Symbol)>1519     crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1520         let (self_, trait_, name) = match self {
1521             QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
1522             _ => return None,
1523         };
1524         Some((&self_, trait_.def_id(), *name))
1525     }
1526 
inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId>1527     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1528         let t: PrimitiveType = match *self {
1529             Type::Path { ref path } => return Some(path.def_id()),
1530             DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
1531             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1532             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1533             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1534             Tuple(ref tys) => {
1535                 if tys.is_empty() {
1536                     PrimitiveType::Unit
1537                 } else {
1538                     PrimitiveType::Tuple
1539                 }
1540             }
1541             BareFunction(..) => PrimitiveType::Fn,
1542             Slice(..) => PrimitiveType::Slice,
1543             Array(..) => PrimitiveType::Array,
1544             RawPointer(..) => PrimitiveType::RawPointer,
1545             QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1546             Generic(_) | Infer | ImplTrait(_) => return None,
1547         };
1548         cache.and_then(|c| Primitive(t).def_id(c))
1549     }
1550 
1551     /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1552     ///
1553     /// See [`Self::def_id_no_primitives`] for more.
1554     ///
1555     /// [clean]: crate::clean
def_id(&self, cache: &Cache) -> Option<DefId>1556     crate fn def_id(&self, cache: &Cache) -> Option<DefId> {
1557         self.inner_def_id(Some(cache))
1558     }
1559 
1560     /// Use this method to get the [`DefId`] of a [`clean`] AST node.
1561     /// This will return [`None`] when called on a primitive [`clean::Type`].
1562     /// Use [`Self::def_id`] if you want to include primitives.
1563     ///
1564     /// [`clean`]: crate::clean
1565     /// [`clean::Type`]: crate::clean::Type
1566     // FIXME: get rid of this function and always use `def_id`
def_id_no_primitives(&self) -> Option<DefId>1567     crate fn def_id_no_primitives(&self) -> Option<DefId> {
1568         self.inner_def_id(None)
1569     }
1570 }
1571 
1572 /// A primitive (aka, builtin) type.
1573 ///
1574 /// This represents things like `i32`, `str`, etc.
1575 ///
1576 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1577 /// paths, like [`Self::Unit`].
1578 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1579 crate enum PrimitiveType {
1580     Isize,
1581     I8,
1582     I16,
1583     I32,
1584     I64,
1585     I128,
1586     Usize,
1587     U8,
1588     U16,
1589     U32,
1590     U64,
1591     U128,
1592     F32,
1593     F64,
1594     Char,
1595     Bool,
1596     Str,
1597     Slice,
1598     Array,
1599     Tuple,
1600     Unit,
1601     RawPointer,
1602     Reference,
1603     Fn,
1604     Never,
1605 }
1606 
1607 impl PrimitiveType {
from_hir(prim: hir::PrimTy) -> PrimitiveType1608     crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1609         use ast::{FloatTy, IntTy, UintTy};
1610         match prim {
1611             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1612             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1613             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1614             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1615             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1616             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1617             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1618             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1619             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1620             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1621             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1622             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1623             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1624             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1625             hir::PrimTy::Str => PrimitiveType::Str,
1626             hir::PrimTy::Bool => PrimitiveType::Bool,
1627             hir::PrimTy::Char => PrimitiveType::Char,
1628         }
1629     }
1630 
from_symbol(s: Symbol) -> Option<PrimitiveType>1631     crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1632         match s {
1633             sym::isize => Some(PrimitiveType::Isize),
1634             sym::i8 => Some(PrimitiveType::I8),
1635             sym::i16 => Some(PrimitiveType::I16),
1636             sym::i32 => Some(PrimitiveType::I32),
1637             sym::i64 => Some(PrimitiveType::I64),
1638             sym::i128 => Some(PrimitiveType::I128),
1639             sym::usize => Some(PrimitiveType::Usize),
1640             sym::u8 => Some(PrimitiveType::U8),
1641             sym::u16 => Some(PrimitiveType::U16),
1642             sym::u32 => Some(PrimitiveType::U32),
1643             sym::u64 => Some(PrimitiveType::U64),
1644             sym::u128 => Some(PrimitiveType::U128),
1645             sym::bool => Some(PrimitiveType::Bool),
1646             sym::char => Some(PrimitiveType::Char),
1647             sym::str => Some(PrimitiveType::Str),
1648             sym::f32 => Some(PrimitiveType::F32),
1649             sym::f64 => Some(PrimitiveType::F64),
1650             sym::array => Some(PrimitiveType::Array),
1651             sym::slice => Some(PrimitiveType::Slice),
1652             sym::tuple => Some(PrimitiveType::Tuple),
1653             sym::unit => Some(PrimitiveType::Unit),
1654             sym::pointer => Some(PrimitiveType::RawPointer),
1655             sym::reference => Some(PrimitiveType::Reference),
1656             kw::Fn => Some(PrimitiveType::Fn),
1657             sym::never => Some(PrimitiveType::Never),
1658             _ => None,
1659         }
1660     }
1661 
impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4>1662     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
1663         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1664     }
1665 
all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>1666     crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>> {
1667         static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>> = OnceCell::new();
1668 
1669         CELL.get_or_init(move || {
1670             use self::PrimitiveType::*;
1671 
1672             let single = |a: Option<DefId>| a.into_iter().collect();
1673             let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_, 4> {
1674                 a.into_iter().chain(b).collect()
1675             };
1676 
1677             let lang_items = tcx.lang_items();
1678             map! {
1679                 Isize => single(lang_items.isize_impl()),
1680                 I8 => single(lang_items.i8_impl()),
1681                 I16 => single(lang_items.i16_impl()),
1682                 I32 => single(lang_items.i32_impl()),
1683                 I64 => single(lang_items.i64_impl()),
1684                 I128 => single(lang_items.i128_impl()),
1685                 Usize => single(lang_items.usize_impl()),
1686                 U8 => single(lang_items.u8_impl()),
1687                 U16 => single(lang_items.u16_impl()),
1688                 U32 => single(lang_items.u32_impl()),
1689                 U64 => single(lang_items.u64_impl()),
1690                 U128 => single(lang_items.u128_impl()),
1691                 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1692                 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1693                 Char => single(lang_items.char_impl()),
1694                 Bool => single(lang_items.bool_impl()),
1695                 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1696                 Slice => {
1697                     lang_items
1698                         .slice_impl()
1699                         .into_iter()
1700                         .chain(lang_items.slice_u8_impl())
1701                         .chain(lang_items.slice_alloc_impl())
1702                         .chain(lang_items.slice_u8_alloc_impl())
1703                         .collect()
1704                 },
1705                 Array => single(lang_items.array_impl()),
1706                 Tuple => ArrayVec::new(),
1707                 Unit => ArrayVec::new(),
1708                 RawPointer => {
1709                     lang_items
1710                         .const_ptr_impl()
1711                         .into_iter()
1712                         .chain(lang_items.mut_ptr_impl())
1713                         .chain(lang_items.const_slice_ptr_impl())
1714                         .chain(lang_items.mut_slice_ptr_impl())
1715                         .collect()
1716                 },
1717                 Reference => ArrayVec::new(),
1718                 Fn => ArrayVec::new(),
1719                 Never => ArrayVec::new(),
1720             }
1721         })
1722     }
1723 
as_sym(&self) -> Symbol1724     crate fn as_sym(&self) -> Symbol {
1725         use PrimitiveType::*;
1726         match self {
1727             Isize => sym::isize,
1728             I8 => sym::i8,
1729             I16 => sym::i16,
1730             I32 => sym::i32,
1731             I64 => sym::i64,
1732             I128 => sym::i128,
1733             Usize => sym::usize,
1734             U8 => sym::u8,
1735             U16 => sym::u16,
1736             U32 => sym::u32,
1737             U64 => sym::u64,
1738             U128 => sym::u128,
1739             F32 => sym::f32,
1740             F64 => sym::f64,
1741             Str => sym::str,
1742             Bool => sym::bool,
1743             Char => sym::char,
1744             Array => sym::array,
1745             Slice => sym::slice,
1746             Tuple => sym::tuple,
1747             Unit => sym::unit,
1748             RawPointer => sym::pointer,
1749             Reference => sym::reference,
1750             Fn => kw::Fn,
1751             Never => sym::never,
1752         }
1753     }
1754 
1755     /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1756     /// Panics if there is no such module.
1757     ///
1758     /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1759     /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1760     /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1761     /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId>1762     crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1763         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1764         PRIMITIVE_LOCATIONS.get_or_init(|| {
1765             let mut primitive_locations = FxHashMap::default();
1766             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1767             // This is a degenerate case that I don't plan to support.
1768             for &crate_num in tcx.crates(()) {
1769                 let e = ExternalCrate { crate_num };
1770                 let crate_name = e.name(tcx);
1771                 debug!(?crate_num, ?crate_name);
1772                 for &(def_id, prim) in &e.primitives(tcx) {
1773                     // HACK: try to link to std instead where possible
1774                     if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1775                         continue;
1776                     }
1777                     primitive_locations.insert(prim, def_id);
1778                 }
1779             }
1780             let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1781             for (def_id, prim) in local_primitives {
1782                 primitive_locations.insert(prim, def_id);
1783             }
1784             primitive_locations
1785         })
1786     }
1787 }
1788 
1789 impl From<ast::IntTy> for PrimitiveType {
from(int_ty: ast::IntTy) -> PrimitiveType1790     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1791         match int_ty {
1792             ast::IntTy::Isize => PrimitiveType::Isize,
1793             ast::IntTy::I8 => PrimitiveType::I8,
1794             ast::IntTy::I16 => PrimitiveType::I16,
1795             ast::IntTy::I32 => PrimitiveType::I32,
1796             ast::IntTy::I64 => PrimitiveType::I64,
1797             ast::IntTy::I128 => PrimitiveType::I128,
1798         }
1799     }
1800 }
1801 
1802 impl From<ast::UintTy> for PrimitiveType {
from(uint_ty: ast::UintTy) -> PrimitiveType1803     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1804         match uint_ty {
1805             ast::UintTy::Usize => PrimitiveType::Usize,
1806             ast::UintTy::U8 => PrimitiveType::U8,
1807             ast::UintTy::U16 => PrimitiveType::U16,
1808             ast::UintTy::U32 => PrimitiveType::U32,
1809             ast::UintTy::U64 => PrimitiveType::U64,
1810             ast::UintTy::U128 => PrimitiveType::U128,
1811         }
1812     }
1813 }
1814 
1815 impl From<ast::FloatTy> for PrimitiveType {
from(float_ty: ast::FloatTy) -> PrimitiveType1816     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1817         match float_ty {
1818             ast::FloatTy::F32 => PrimitiveType::F32,
1819             ast::FloatTy::F64 => PrimitiveType::F64,
1820         }
1821     }
1822 }
1823 
1824 impl From<ty::IntTy> for PrimitiveType {
from(int_ty: ty::IntTy) -> PrimitiveType1825     fn from(int_ty: ty::IntTy) -> PrimitiveType {
1826         match int_ty {
1827             ty::IntTy::Isize => PrimitiveType::Isize,
1828             ty::IntTy::I8 => PrimitiveType::I8,
1829             ty::IntTy::I16 => PrimitiveType::I16,
1830             ty::IntTy::I32 => PrimitiveType::I32,
1831             ty::IntTy::I64 => PrimitiveType::I64,
1832             ty::IntTy::I128 => PrimitiveType::I128,
1833         }
1834     }
1835 }
1836 
1837 impl From<ty::UintTy> for PrimitiveType {
from(uint_ty: ty::UintTy) -> PrimitiveType1838     fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1839         match uint_ty {
1840             ty::UintTy::Usize => PrimitiveType::Usize,
1841             ty::UintTy::U8 => PrimitiveType::U8,
1842             ty::UintTy::U16 => PrimitiveType::U16,
1843             ty::UintTy::U32 => PrimitiveType::U32,
1844             ty::UintTy::U64 => PrimitiveType::U64,
1845             ty::UintTy::U128 => PrimitiveType::U128,
1846         }
1847     }
1848 }
1849 
1850 impl From<ty::FloatTy> for PrimitiveType {
from(float_ty: ty::FloatTy) -> PrimitiveType1851     fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1852         match float_ty {
1853             ty::FloatTy::F32 => PrimitiveType::F32,
1854             ty::FloatTy::F64 => PrimitiveType::F64,
1855         }
1856     }
1857 }
1858 
1859 impl From<hir::PrimTy> for PrimitiveType {
from(prim_ty: hir::PrimTy) -> PrimitiveType1860     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1861         match prim_ty {
1862             hir::PrimTy::Int(int_ty) => int_ty.into(),
1863             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1864             hir::PrimTy::Float(float_ty) => float_ty.into(),
1865             hir::PrimTy::Str => PrimitiveType::Str,
1866             hir::PrimTy::Bool => PrimitiveType::Bool,
1867             hir::PrimTy::Char => PrimitiveType::Char,
1868         }
1869     }
1870 }
1871 
1872 #[derive(Copy, Clone, Debug)]
1873 crate enum Visibility {
1874     /// `pub`
1875     Public,
1876     /// Visibility inherited from parent.
1877     ///
1878     /// For example, this is the visibility of private items and of enum variants.
1879     Inherited,
1880     /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
1881     Restricted(DefId),
1882 }
1883 
1884 impl Visibility {
is_public(&self) -> bool1885     crate fn is_public(&self) -> bool {
1886         matches!(self, Visibility::Public)
1887     }
1888 }
1889 
1890 #[derive(Clone, Debug)]
1891 crate struct Struct {
1892     crate struct_type: CtorKind,
1893     crate generics: Generics,
1894     crate fields: Vec<Item>,
1895     crate fields_stripped: bool,
1896 }
1897 
1898 #[derive(Clone, Debug)]
1899 crate struct Union {
1900     crate generics: Generics,
1901     crate fields: Vec<Item>,
1902     crate fields_stripped: bool,
1903 }
1904 
1905 /// This is a more limited form of the standard Struct, different in that
1906 /// it lacks the things most items have (name, id, parameterization). Found
1907 /// only as a variant in an enum.
1908 #[derive(Clone, Debug)]
1909 crate struct VariantStruct {
1910     crate struct_type: CtorKind,
1911     crate fields: Vec<Item>,
1912     crate fields_stripped: bool,
1913 }
1914 
1915 #[derive(Clone, Debug)]
1916 crate struct Enum {
1917     crate variants: IndexVec<VariantIdx, Item>,
1918     crate generics: Generics,
1919     crate variants_stripped: bool,
1920 }
1921 
1922 #[derive(Clone, Debug)]
1923 crate enum Variant {
1924     CLike,
1925     Tuple(Vec<Item>),
1926     Struct(VariantStruct),
1927 }
1928 
1929 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
1930 /// and enforces calling [`rustc_span::Span::source_callsite()`].
1931 #[derive(Copy, Clone, Debug)]
1932 crate struct Span(rustc_span::Span);
1933 
1934 impl Span {
1935     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
1936     /// span will be updated to point to the macro invocation instead of the macro definition.
1937     ///
1938     /// (See rust-lang/rust#39726)
new(sp: rustc_span::Span) -> Self1939     crate fn new(sp: rustc_span::Span) -> Self {
1940         Self(sp.source_callsite())
1941     }
1942 
inner(&self) -> rustc_span::Span1943     crate fn inner(&self) -> rustc_span::Span {
1944         self.0
1945     }
1946 
dummy() -> Self1947     crate fn dummy() -> Self {
1948         Self(rustc_span::DUMMY_SP)
1949     }
1950 
is_dummy(&self) -> bool1951     crate fn is_dummy(&self) -> bool {
1952         self.0.is_dummy()
1953     }
1954 
filename(&self, sess: &Session) -> FileName1955     crate fn filename(&self, sess: &Session) -> FileName {
1956         sess.source_map().span_to_filename(self.0)
1957     }
1958 
lo(&self, sess: &Session) -> Loc1959     crate fn lo(&self, sess: &Session) -> Loc {
1960         sess.source_map().lookup_char_pos(self.0.lo())
1961     }
1962 
hi(&self, sess: &Session) -> Loc1963     crate fn hi(&self, sess: &Session) -> Loc {
1964         sess.source_map().lookup_char_pos(self.0.hi())
1965     }
1966 
cnum(&self, sess: &Session) -> CrateNum1967     crate fn cnum(&self, sess: &Session) -> CrateNum {
1968         // FIXME: is there a time when the lo and hi crate would be different?
1969         self.lo(sess).file.cnum
1970     }
1971 }
1972 
1973 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1974 crate struct Path {
1975     crate res: Res,
1976     crate segments: Vec<PathSegment>,
1977 }
1978 
1979 impl Path {
def_id(&self) -> DefId1980     crate fn def_id(&self) -> DefId {
1981         self.res.def_id()
1982     }
1983 
last(&self) -> Symbol1984     crate fn last(&self) -> Symbol {
1985         self.segments.last().expect("segments were empty").name
1986     }
1987 
last_name(&self) -> SymbolStr1988     crate fn last_name(&self) -> SymbolStr {
1989         self.segments.last().expect("segments were empty").name.as_str()
1990     }
1991 
whole_name(&self) -> String1992     crate fn whole_name(&self) -> String {
1993         self.segments
1994             .iter()
1995             .map(|s| if s.name == kw::PathRoot { String::new() } else { s.name.to_string() })
1996             .intersperse("::".into())
1997             .collect()
1998     }
1999 
2000     /// Checks if this is a `T::Name` path for an associated type.
is_assoc_ty(&self) -> bool2001     crate fn is_assoc_ty(&self) -> bool {
2002         match self.res {
2003             Res::SelfTy(..) if self.segments.len() != 1 => true,
2004             Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
2005             Res::Def(DefKind::AssocTy, _) => true,
2006             _ => false,
2007         }
2008     }
2009 
generics(&self) -> Option<Vec<&Type>>2010     crate fn generics(&self) -> Option<Vec<&Type>> {
2011         self.segments.last().and_then(|seg| {
2012             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2013                 Some(
2014                     args.iter()
2015                         .filter_map(|arg| match arg {
2016                             GenericArg::Type(ty) => Some(ty),
2017                             _ => None,
2018                         })
2019                         .collect(),
2020                 )
2021             } else {
2022                 None
2023             }
2024         })
2025     }
2026 
bindings(&self) -> Option<&[TypeBinding]>2027     crate fn bindings(&self) -> Option<&[TypeBinding]> {
2028         self.segments.last().and_then(|seg| {
2029             if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2030                 Some(&**bindings)
2031             } else {
2032                 None
2033             }
2034         })
2035     }
2036 }
2037 
2038 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2039 crate enum GenericArg {
2040     Lifetime(Lifetime),
2041     Type(Type),
2042     Const(Box<Constant>),
2043     Infer,
2044 }
2045 
2046 // `GenericArg` can occur many times in a single `Path`, so make sure it
2047 // doesn't increase in size unexpectedly.
2048 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2049 rustc_data_structures::static_assert_size!(GenericArg, 80);
2050 
2051 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2052 crate enum GenericArgs {
2053     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
2054     Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
2055 }
2056 
2057 // `GenericArgs` is in every `PathSegment`, so its size can significantly
2058 // affect rustdoc's memory usage.
2059 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2060 rustc_data_structures::static_assert_size!(GenericArgs, 56);
2061 
2062 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2063 crate struct PathSegment {
2064     crate name: Symbol,
2065     crate args: GenericArgs,
2066 }
2067 
2068 // `PathSegment` usually occurs multiple times in every `Path`, so its size can
2069 // significantly affect rustdoc's memory usage.
2070 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2071 rustc_data_structures::static_assert_size!(PathSegment, 64);
2072 
2073 #[derive(Clone, Debug)]
2074 crate struct Typedef {
2075     crate type_: Type,
2076     crate generics: Generics,
2077     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2078     /// alias instead of the final type. This will always have the final type, regardless of whether
2079     /// `type_` came from HIR or from metadata.
2080     ///
2081     /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
2082     /// final type).
2083     crate item_type: Option<Type>,
2084 }
2085 
2086 #[derive(Clone, Debug)]
2087 crate struct OpaqueTy {
2088     crate bounds: Vec<GenericBound>,
2089     crate generics: Generics,
2090 }
2091 
2092 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2093 crate struct BareFunctionDecl {
2094     crate unsafety: hir::Unsafety,
2095     crate generic_params: Vec<GenericParamDef>,
2096     crate decl: FnDecl,
2097     crate abi: Abi,
2098 }
2099 
2100 #[derive(Clone, Debug)]
2101 crate struct Static {
2102     crate type_: Type,
2103     crate mutability: Mutability,
2104     crate expr: Option<BodyId>,
2105 }
2106 
2107 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2108 crate struct Constant {
2109     crate type_: Type,
2110     crate kind: ConstantKind,
2111 }
2112 
2113 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2114 crate enum ConstantKind {
2115     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2116     /// `BodyId`, we need to handle it on its own.
2117     ///
2118     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2119     /// by a DefId. So this field must be different from `Extern`.
2120     TyConst { expr: String },
2121     /// A constant (expression) that's not an item or associated item. These are usually found
2122     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2123     /// used to define explicit discriminant values for enum variants.
2124     Anonymous { body: BodyId },
2125     /// A constant from a different crate.
2126     Extern { def_id: DefId },
2127     /// `const FOO: u32 = ...;`
2128     Local { def_id: DefId, body: BodyId },
2129 }
2130 
2131 impl Constant {
expr(&self, tcx: TyCtxt<'_>) -> String2132     crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
2133         match self.kind {
2134             ConstantKind::TyConst { ref expr } => expr.clone(),
2135             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2136             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2137                 print_const_expr(tcx, body)
2138             }
2139         }
2140     }
2141 
value(&self, tcx: TyCtxt<'_>) -> Option<String>2142     crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2143         match self.kind {
2144             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2145             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2146                 print_evaluated_const(tcx, def_id)
2147             }
2148         }
2149     }
2150 
is_literal(&self, tcx: TyCtxt<'_>) -> bool2151     crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2152         match self.kind {
2153             ConstantKind::TyConst { .. } => false,
2154             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2155                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2156             }),
2157             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2158                 is_literal_expr(tcx, body.hir_id)
2159             }
2160         }
2161     }
2162 }
2163 
2164 #[derive(Clone, Debug)]
2165 crate struct Impl {
2166     crate unsafety: hir::Unsafety,
2167     crate generics: Generics,
2168     crate trait_: Option<Path>,
2169     crate for_: Type,
2170     crate items: Vec<Item>,
2171     crate polarity: ty::ImplPolarity,
2172     crate kind: ImplKind,
2173 }
2174 
2175 impl Impl {
provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol>2176     crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2177         self.trait_
2178             .as_ref()
2179             .map(|t| t.def_id())
2180             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
2181             .unwrap_or_default()
2182     }
2183 }
2184 
2185 #[derive(Clone, Debug)]
2186 crate enum ImplKind {
2187     Normal,
2188     Auto,
2189     Blanket(Box<Type>),
2190 }
2191 
2192 impl ImplKind {
is_auto(&self) -> bool2193     crate fn is_auto(&self) -> bool {
2194         matches!(self, ImplKind::Auto)
2195     }
2196 
is_blanket(&self) -> bool2197     crate fn is_blanket(&self) -> bool {
2198         matches!(self, ImplKind::Blanket(_))
2199     }
2200 
as_blanket_ty(&self) -> Option<&Type>2201     crate fn as_blanket_ty(&self) -> Option<&Type> {
2202         match self {
2203             ImplKind::Blanket(ty) => Some(ty),
2204             _ => None,
2205         }
2206     }
2207 }
2208 
2209 #[derive(Clone, Debug)]
2210 crate struct Import {
2211     crate kind: ImportKind,
2212     crate source: ImportSource,
2213     crate should_be_displayed: bool,
2214 }
2215 
2216 impl Import {
new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self2217     crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
2218         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2219     }
2220 
new_glob(source: ImportSource, should_be_displayed: bool) -> Self2221     crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2222         Self { kind: ImportKind::Glob, source, should_be_displayed }
2223     }
2224 }
2225 
2226 #[derive(Clone, Debug)]
2227 crate enum ImportKind {
2228     // use source as str;
2229     Simple(Symbol),
2230     // use source::*;
2231     Glob,
2232 }
2233 
2234 #[derive(Clone, Debug)]
2235 crate struct ImportSource {
2236     crate path: Path,
2237     crate did: Option<DefId>,
2238 }
2239 
2240 #[derive(Clone, Debug)]
2241 crate struct Macro {
2242     crate source: String,
2243 }
2244 
2245 #[derive(Clone, Debug)]
2246 crate struct ProcMacro {
2247     crate kind: MacroKind,
2248     crate helpers: Vec<Symbol>,
2249 }
2250 
2251 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2252 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2253 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2254 crate struct TypeBinding {
2255     crate name: Symbol,
2256     crate kind: TypeBindingKind,
2257 }
2258 
2259 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2260 crate enum TypeBindingKind {
2261     Equality { ty: Type },
2262     Constraint { bounds: Vec<GenericBound> },
2263 }
2264 
2265 impl TypeBinding {
ty(&self) -> &Type2266     crate fn ty(&self) -> &Type {
2267         match self.kind {
2268             TypeBindingKind::Equality { ref ty } => ty,
2269             _ => panic!("expected equality type binding for parenthesized generic args"),
2270         }
2271     }
2272 }
2273 
2274 /// The type, lifetime, or constant that a private type alias's parameter should be
2275 /// replaced with when expanding a use of that type alias.
2276 ///
2277 /// For example:
2278 ///
2279 /// ```
2280 /// type PrivAlias<T> = Vec<T>;
2281 ///
2282 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2283 /// ```
2284 ///
2285 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2286 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2287 crate enum SubstParam {
2288     Type(Type),
2289     Lifetime(Lifetime),
2290     Constant(Constant),
2291 }
2292 
2293 impl SubstParam {
as_ty(&self) -> Option<&Type>2294     crate fn as_ty(&self) -> Option<&Type> {
2295         if let Self::Type(ty) = self { Some(ty) } else { None }
2296     }
2297 
as_lt(&self) -> Option<&Lifetime>2298     crate fn as_lt(&self) -> Option<&Lifetime> {
2299         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2300     }
2301 }
2302