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