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