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