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