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