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