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