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