]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Fix font color for help button in ayu and dark themes
[rust.git] / src / librustdoc / clean / types.rs
1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::fmt;
4 use std::hash::{Hash, Hasher};
5 use std::iter::FromIterator;
6 use std::lazy::SyncOnceCell as OnceCell;
7 use std::num::NonZeroU32;
8 use std::rc::Rc;
9 use std::sync::Arc;
10 use std::{slice, vec};
11
12 use rustc_ast::attr;
13 use rustc_ast::util::comments::beautify_doc_string;
14 use rustc_ast::{self as ast, AttrStyle};
15 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
16 use rustc_hir as hir;
17 use rustc_hir::def::Res;
18 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
19 use rustc_hir::lang_items;
20 use rustc_hir::Mutability;
21 use rustc_index::vec::IndexVec;
22 use rustc_middle::middle::stability;
23 use rustc_middle::ty::TyCtxt;
24 use rustc_span::hygiene::MacroKind;
25 use rustc_span::source_map::DUMMY_SP;
26 use rustc_span::symbol::{kw, sym, Ident, Symbol};
27 use rustc_span::{self, FileName};
28 use rustc_target::abi::VariantIdx;
29 use rustc_target::spec::abi::Abi;
30 use smallvec::{smallvec, SmallVec};
31
32 use crate::clean::cfg::Cfg;
33 use crate::clean::external_path;
34 use crate::clean::inline;
35 use crate::clean::types::Type::{QPath, ResolvedPath};
36 use crate::core::DocContext;
37 use crate::doctree;
38 use crate::formats::cache::cache;
39 use crate::formats::item_type::ItemType;
40 use crate::html::render::cache::ExternalLocation;
41
42 use self::FnRetTy::*;
43 use self::ItemEnum::*;
44 use self::SelfTy::*;
45 use self::Type::*;
46
47 thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
48
49 #[derive(Clone, Debug)]
50 pub struct Crate {
51     pub name: String,
52     pub version: Option<String>,
53     pub src: FileName,
54     pub module: Option<Item>,
55     pub externs: Vec<(CrateNum, ExternalCrate)>,
56     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
57     // These are later on moved into `CACHEKEY`, leaving the map empty.
58     // Only here so that they can be filtered through the rustdoc passes.
59     pub external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
60     pub masked_crates: FxHashSet<CrateNum>,
61     pub collapsed: bool,
62 }
63
64 #[derive(Clone, Debug)]
65 pub struct ExternalCrate {
66     pub name: String,
67     pub src: FileName,
68     pub attrs: Attributes,
69     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
70     pub keywords: Vec<(DefId, String, Attributes)>,
71 }
72
73 /// Anything with a source location and set of attributes and, optionally, a
74 /// name. That is, anything that can be documented. This doesn't correspond
75 /// directly to the AST's concept of an item; it's a strict superset.
76 #[derive(Clone)]
77 pub struct Item {
78     /// Stringified span
79     pub source: Span,
80     /// Not everything has a name. E.g., impls
81     pub name: Option<String>,
82     pub attrs: Attributes,
83     pub inner: ItemEnum,
84     pub visibility: Visibility,
85     pub def_id: DefId,
86     pub stability: Option<Stability>,
87     pub deprecation: Option<Deprecation>,
88 }
89
90 impl fmt::Debug for Item {
91     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
92         let fake = self.is_fake();
93         let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
94
95         fmt.debug_struct("Item")
96             .field("source", &self.source)
97             .field("name", &self.name)
98             .field("attrs", &self.attrs)
99             .field("inner", &self.inner)
100             .field("visibility", &self.visibility)
101             .field("def_id", def_id)
102             .field("stability", &self.stability)
103             .field("deprecation", &self.deprecation)
104             .finish()
105     }
106 }
107
108 impl Item {
109     /// Finds the `doc` attribute as a NameValue and returns the corresponding
110     /// value found.
111     pub fn doc_value(&self) -> Option<&str> {
112         self.attrs.doc_value()
113     }
114
115     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
116     /// with newlines.
117     pub fn collapsed_doc_value(&self) -> Option<String> {
118         self.attrs.collapsed_doc_value()
119     }
120
121     pub fn links(&self) -> Vec<(String, String)> {
122         self.attrs.links(&self.def_id.krate)
123     }
124
125     pub fn is_crate(&self) -> bool {
126         match self.inner {
127             StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
128             | ModuleItem(Module { is_crate: true, .. }) => true,
129             _ => false,
130         }
131     }
132     pub fn is_mod(&self) -> bool {
133         self.type_() == ItemType::Module
134     }
135     pub fn is_trait(&self) -> bool {
136         self.type_() == ItemType::Trait
137     }
138     pub fn is_struct(&self) -> bool {
139         self.type_() == ItemType::Struct
140     }
141     pub fn is_enum(&self) -> bool {
142         self.type_() == ItemType::Enum
143     }
144     pub fn is_variant(&self) -> bool {
145         self.type_() == ItemType::Variant
146     }
147     pub fn is_associated_type(&self) -> bool {
148         self.type_() == ItemType::AssocType
149     }
150     pub fn is_associated_const(&self) -> bool {
151         self.type_() == ItemType::AssocConst
152     }
153     pub fn is_method(&self) -> bool {
154         self.type_() == ItemType::Method
155     }
156     pub fn is_ty_method(&self) -> bool {
157         self.type_() == ItemType::TyMethod
158     }
159     pub fn is_typedef(&self) -> bool {
160         self.type_() == ItemType::Typedef
161     }
162     pub fn is_primitive(&self) -> bool {
163         self.type_() == ItemType::Primitive
164     }
165     pub fn is_union(&self) -> bool {
166         self.type_() == ItemType::Union
167     }
168     pub fn is_import(&self) -> bool {
169         self.type_() == ItemType::Import
170     }
171     pub fn is_extern_crate(&self) -> bool {
172         self.type_() == ItemType::ExternCrate
173     }
174     pub fn is_keyword(&self) -> bool {
175         self.type_() == ItemType::Keyword
176     }
177     pub fn is_stripped(&self) -> bool {
178         match self.inner {
179             StrippedItem(..) => true,
180             _ => false,
181         }
182     }
183     pub fn has_stripped_fields(&self) -> Option<bool> {
184         match self.inner {
185             StructItem(ref _struct) => Some(_struct.fields_stripped),
186             UnionItem(ref union) => Some(union.fields_stripped),
187             VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
188                 Some(vstruct.fields_stripped)
189             }
190             _ => None,
191         }
192     }
193
194     pub fn stability_class(&self) -> Option<String> {
195         self.stability.as_ref().and_then(|ref s| {
196             let mut classes = Vec::with_capacity(2);
197
198             if s.level == stability::Unstable {
199                 classes.push("unstable");
200             }
201
202             // FIXME: what about non-staged API items that are deprecated?
203             if self.deprecation.is_some() {
204                 classes.push("deprecated");
205             }
206
207             if !classes.is_empty() { Some(classes.join(" ")) } else { None }
208         })
209     }
210
211     pub fn stable_since(&self) -> Option<&str> {
212         self.stability.as_ref().map(|s| &s.since[..])
213     }
214
215     pub fn is_non_exhaustive(&self) -> bool {
216         self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
217     }
218
219     /// Returns a documentation-level item type from the item.
220     pub fn type_(&self) -> ItemType {
221         ItemType::from(self)
222     }
223
224     pub fn is_default(&self) -> bool {
225         match self.inner {
226             ItemEnum::MethodItem(ref meth) => {
227                 if let Some(defaultness) = meth.defaultness {
228                     defaultness.has_value() && !defaultness.is_final()
229                 } else {
230                     false
231                 }
232             }
233             _ => false,
234         }
235     }
236
237     /// See comments on next_def_id
238     pub fn is_fake(&self) -> bool {
239         MAX_DEF_ID.with(|m| {
240             m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
241         })
242     }
243 }
244
245 #[derive(Clone, Debug)]
246 pub enum ItemEnum {
247     ExternCrateItem(String, Option<String>),
248     ImportItem(Import),
249     StructItem(Struct),
250     UnionItem(Union),
251     EnumItem(Enum),
252     FunctionItem(Function),
253     ModuleItem(Module),
254     TypedefItem(Typedef, bool /* is associated type */),
255     OpaqueTyItem(OpaqueTy, bool /* is associated type */),
256     StaticItem(Static),
257     ConstantItem(Constant),
258     TraitItem(Trait),
259     TraitAliasItem(TraitAlias),
260     ImplItem(Impl),
261     /// A method signature only. Used for required methods in traits (ie,
262     /// non-default-methods).
263     TyMethodItem(TyMethod),
264     /// A method with a body.
265     MethodItem(Method),
266     StructFieldItem(Type),
267     VariantItem(Variant),
268     /// `fn`s from an extern block
269     ForeignFunctionItem(Function),
270     /// `static`s from an extern block
271     ForeignStaticItem(Static),
272     /// `type`s from an extern block
273     ForeignTypeItem,
274     MacroItem(Macro),
275     ProcMacroItem(ProcMacro),
276     PrimitiveItem(PrimitiveType),
277     AssocConstItem(Type, Option<String>),
278     AssocTypeItem(Vec<GenericBound>, Option<Type>),
279     /// An item that has been stripped by a rustdoc pass
280     StrippedItem(Box<ItemEnum>),
281     KeywordItem(String),
282 }
283
284 impl ItemEnum {
285     pub fn is_associated(&self) -> bool {
286         match *self {
287             ItemEnum::TypedefItem(_, _) | ItemEnum::AssocTypeItem(_, _) => true,
288             _ => false,
289         }
290     }
291 }
292
293 #[derive(Clone, Debug)]
294 pub struct Module {
295     pub items: Vec<Item>,
296     pub is_crate: bool,
297 }
298
299 pub struct ListAttributesIter<'a> {
300     attrs: slice::Iter<'a, ast::Attribute>,
301     current_list: vec::IntoIter<ast::NestedMetaItem>,
302     name: Symbol,
303 }
304
305 impl<'a> Iterator for ListAttributesIter<'a> {
306     type Item = ast::NestedMetaItem;
307
308     fn next(&mut self) -> Option<Self::Item> {
309         if let Some(nested) = self.current_list.next() {
310             return Some(nested);
311         }
312
313         for attr in &mut self.attrs {
314             if let Some(list) = attr.meta_item_list() {
315                 if attr.has_name(self.name) {
316                     self.current_list = list.into_iter();
317                     if let Some(nested) = self.current_list.next() {
318                         return Some(nested);
319                     }
320                 }
321             }
322         }
323
324         None
325     }
326
327     fn size_hint(&self) -> (usize, Option<usize>) {
328         let lower = self.current_list.len();
329         (lower, None)
330     }
331 }
332
333 pub trait AttributesExt {
334     /// Finds an attribute as List and returns the list of attributes nested inside.
335     fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
336 }
337
338 impl AttributesExt for [ast::Attribute] {
339     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
340         ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
341     }
342 }
343
344 pub trait NestedAttributesExt {
345     /// Returns `true` if the attribute list contains a specific `Word`
346     fn has_word(self, word: Symbol) -> bool;
347 }
348
349 impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
350     fn has_word(self, word: Symbol) -> bool {
351         self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
352     }
353 }
354
355 /// A portion of documentation, extracted from a `#[doc]` attribute.
356 ///
357 /// Each variant contains the line number within the complete doc-comment where the fragment
358 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
359 ///
360 /// Included files are kept separate from inline doc comments so that proper line-number
361 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
362 /// kept separate because of issue #42760.
363 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
364 pub enum DocFragment {
365     /// A doc fragment created from a `///` or `//!` doc comment.
366     SugaredDoc(usize, rustc_span::Span, String),
367     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
368     RawDoc(usize, rustc_span::Span, String),
369     /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
370     /// given filename and the file contents.
371     Include(usize, rustc_span::Span, String, String),
372 }
373
374 impl DocFragment {
375     pub fn as_str(&self) -> &str {
376         match *self {
377             DocFragment::SugaredDoc(_, _, ref s) => &s[..],
378             DocFragment::RawDoc(_, _, ref s) => &s[..],
379             DocFragment::Include(_, _, _, ref s) => &s[..],
380         }
381     }
382
383     pub fn span(&self) -> rustc_span::Span {
384         match *self {
385             DocFragment::SugaredDoc(_, span, _)
386             | DocFragment::RawDoc(_, span, _)
387             | DocFragment::Include(_, span, _, _) => span,
388         }
389     }
390 }
391
392 impl<'a> FromIterator<&'a DocFragment> for String {
393     fn from_iter<T>(iter: T) -> Self
394     where
395         T: IntoIterator<Item = &'a DocFragment>,
396     {
397         iter.into_iter().fold(String::new(), |mut acc, frag| {
398             if !acc.is_empty() {
399                 acc.push('\n');
400             }
401             match *frag {
402                 DocFragment::SugaredDoc(_, _, ref docs)
403                 | DocFragment::RawDoc(_, _, ref docs)
404                 | DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
405             }
406
407             acc
408         })
409     }
410 }
411
412 #[derive(Clone, Debug, Default)]
413 pub struct Attributes {
414     pub doc_strings: Vec<DocFragment>,
415     pub other_attrs: Vec<ast::Attribute>,
416     pub cfg: Option<Arc<Cfg>>,
417     pub span: Option<rustc_span::Span>,
418     /// map from Rust paths to resolved defs and potential URL fragments
419     pub links: Vec<(String, Option<DefId>, Option<String>)>,
420     pub inner_docs: bool,
421 }
422
423 impl Attributes {
424     /// Extracts the content from an attribute `#[doc(cfg(content))]`.
425     pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
426         use rustc_ast::NestedMetaItem::MetaItem;
427
428         if let ast::MetaItemKind::List(ref nmis) = mi.kind {
429             if nmis.len() == 1 {
430                 if let MetaItem(ref cfg_mi) = nmis[0] {
431                     if cfg_mi.has_name(sym::cfg) {
432                         if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
433                             if cfg_nmis.len() == 1 {
434                                 if let MetaItem(ref content_mi) = cfg_nmis[0] {
435                                     return Some(content_mi);
436                                 }
437                             }
438                         }
439                     }
440                 }
441             }
442         }
443
444         None
445     }
446
447     /// Reads a `MetaItem` from within an attribute, looks for whether it is a
448     /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
449     /// its expansion.
450     pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
451         mi.meta_item_list().and_then(|list| {
452             for meta in list {
453                 if meta.has_name(sym::include) {
454                     // the actual compiled `#[doc(include="filename")]` gets expanded to
455                     // `#[doc(include(file="filename", contents="file contents")]` so we need to
456                     // look for that instead
457                     return meta.meta_item_list().and_then(|list| {
458                         let mut filename: Option<String> = None;
459                         let mut contents: Option<String> = None;
460
461                         for it in list {
462                             if it.has_name(sym::file) {
463                                 if let Some(name) = it.value_str() {
464                                     filename = Some(name.to_string());
465                                 }
466                             } else if it.has_name(sym::contents) {
467                                 if let Some(docs) = it.value_str() {
468                                     contents = Some(docs.to_string());
469                                 }
470                             }
471                         }
472
473                         if let (Some(filename), Some(contents)) = (filename, contents) {
474                             Some((filename, contents))
475                         } else {
476                             None
477                         }
478                     });
479                 }
480             }
481
482             None
483         })
484     }
485
486     pub fn has_doc_flag(&self, flag: Symbol) -> bool {
487         for attr in &self.other_attrs {
488             if !attr.has_name(sym::doc) {
489                 continue;
490             }
491
492             if let Some(items) = attr.meta_item_list() {
493                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
494                     return true;
495                 }
496             }
497         }
498
499         false
500     }
501
502     pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
503         let mut doc_strings = vec![];
504         let mut sp = None;
505         let mut cfg = Cfg::True;
506         let mut doc_line = 0;
507
508         let other_attrs = attrs
509             .iter()
510             .filter_map(|attr| {
511                 if let Some(value) = attr.doc_str() {
512                     let value = beautify_doc_string(value);
513                     let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() {
514                         DocFragment::SugaredDoc
515                     } else {
516                         DocFragment::RawDoc
517                     };
518
519                     let line = doc_line;
520                     doc_line += value.lines().count();
521                     doc_strings.push(mk_fragment(line, attr.span, value));
522
523                     if sp.is_none() {
524                         sp = Some(attr.span);
525                     }
526                     None
527                 } else {
528                     if attr.has_name(sym::doc) {
529                         if let Some(mi) = attr.meta() {
530                             if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
531                                 // Extracted #[doc(cfg(...))]
532                                 match Cfg::parse(cfg_mi) {
533                                     Ok(new_cfg) => cfg &= new_cfg,
534                                     Err(e) => diagnostic.span_err(e.span, e.msg),
535                                 }
536                             } else if let Some((filename, contents)) =
537                                 Attributes::extract_include(&mi)
538                             {
539                                 let line = doc_line;
540                                 doc_line += contents.lines().count();
541                                 doc_strings.push(DocFragment::Include(
542                                     line, attr.span, filename, contents,
543                                 ));
544                             }
545                         }
546                     }
547                     Some(attr.clone())
548                 }
549             })
550             .collect();
551
552         // treat #[target_feature(enable = "feat")] attributes as if they were
553         // #[doc(cfg(target_feature = "feat"))] attributes as well
554         for attr in attrs.lists(sym::target_feature) {
555             if attr.has_name(sym::enable) {
556                 if let Some(feat) = attr.value_str() {
557                     let meta = attr::mk_name_value_item_str(
558                         Ident::with_dummy_span(sym::target_feature),
559                         feat,
560                         DUMMY_SP,
561                     );
562                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
563                         cfg &= feat_cfg;
564                     }
565                 }
566             }
567         }
568
569         let inner_docs = attrs
570             .iter()
571             .find(|a| a.doc_str().is_some())
572             .map_or(true, |a| a.style == AttrStyle::Inner);
573
574         Attributes {
575             doc_strings,
576             other_attrs,
577             cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
578             span: sp,
579             links: vec![],
580             inner_docs,
581         }
582     }
583
584     /// Finds the `doc` attribute as a NameValue and returns the corresponding
585     /// value found.
586     pub fn doc_value(&self) -> Option<&str> {
587         self.doc_strings.first().map(|s| s.as_str())
588     }
589
590     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
591     /// with newlines.
592     pub fn collapsed_doc_value(&self) -> Option<String> {
593         if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
594     }
595
596     /// Gets links as a vector
597     ///
598     /// Cache must be populated before call
599     pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
600         use crate::html::format::href;
601         use crate::html::render::CURRENT_DEPTH;
602
603         self.links
604             .iter()
605             .filter_map(|&(ref s, did, ref fragment)| {
606                 match did {
607                     Some(did) => {
608                         if let Some((mut href, ..)) = href(did) {
609                             if let Some(ref fragment) = *fragment {
610                                 href.push_str("#");
611                                 href.push_str(fragment);
612                             }
613                             Some((s.clone(), href))
614                         } else {
615                             None
616                         }
617                     }
618                     None => {
619                         if let Some(ref fragment) = *fragment {
620                             let cache = cache();
621                             let url = match cache.extern_locations.get(krate) {
622                                 Some(&(_, _, ExternalLocation::Local)) => {
623                                     let depth = CURRENT_DEPTH.with(|l| l.get());
624                                     "../".repeat(depth)
625                                 }
626                                 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
627                                 Some(&(_, _, ExternalLocation::Unknown)) | None => {
628                                     String::from("https://doc.rust-lang.org/nightly")
629                                 }
630                             };
631                             // This is a primitive so the url is done "by hand".
632                             let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
633                             Some((
634                                 s.clone(),
635                                 format!(
636                                     "{}{}std/primitive.{}.html{}",
637                                     url,
638                                     if !url.ends_with('/') { "/" } else { "" },
639                                     &fragment[..tail],
640                                     &fragment[tail..]
641                                 ),
642                             ))
643                         } else {
644                             panic!("This isn't a primitive?!");
645                         }
646                     }
647                 }
648             })
649             .collect()
650     }
651
652     pub fn get_doc_aliases(&self) -> FxHashSet<String> {
653         self.other_attrs
654             .lists(sym::doc)
655             .filter(|a| a.has_name(sym::alias))
656             .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", "")))
657             .filter(|v| !v.is_empty())
658             .collect::<FxHashSet<_>>()
659     }
660 }
661
662 impl PartialEq for Attributes {
663     fn eq(&self, rhs: &Self) -> bool {
664         self.doc_strings == rhs.doc_strings
665             && self.cfg == rhs.cfg
666             && self.span == rhs.span
667             && self.links == rhs.links
668             && self
669                 .other_attrs
670                 .iter()
671                 .map(|attr| attr.id)
672                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
673     }
674 }
675
676 impl Eq for Attributes {}
677
678 impl Hash for Attributes {
679     fn hash<H: Hasher>(&self, hasher: &mut H) {
680         self.doc_strings.hash(hasher);
681         self.cfg.hash(hasher);
682         self.span.hash(hasher);
683         self.links.hash(hasher);
684         for attr in &self.other_attrs {
685             attr.id.hash(hasher);
686         }
687     }
688 }
689
690 impl AttributesExt for Attributes {
691     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
692         self.other_attrs.lists(name)
693     }
694 }
695
696 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
697 pub enum GenericBound {
698     TraitBound(PolyTrait, hir::TraitBoundModifier),
699     Outlives(Lifetime),
700 }
701
702 impl GenericBound {
703     pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
704         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
705         let empty = cx.tcx.intern_substs(&[]);
706         let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
707         inline::record_extern_fqn(cx, did, TypeKind::Trait);
708         GenericBound::TraitBound(
709             PolyTrait {
710                 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
711                 generic_params: Vec::new(),
712             },
713             hir::TraitBoundModifier::Maybe,
714         )
715     }
716
717     pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
718         use rustc_hir::TraitBoundModifier as TBM;
719         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
720             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
721                 return true;
722             }
723         }
724         false
725     }
726
727     pub fn get_poly_trait(&self) -> Option<PolyTrait> {
728         if let GenericBound::TraitBound(ref p, _) = *self {
729             return Some(p.clone());
730         }
731         None
732     }
733
734     pub fn get_trait_type(&self) -> Option<Type> {
735         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
736             Some(trait_.clone())
737         } else {
738             None
739         }
740     }
741 }
742
743 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
744 pub struct Lifetime(pub String);
745
746 impl Lifetime {
747     pub fn get_ref<'a>(&'a self) -> &'a str {
748         let Lifetime(ref s) = *self;
749         let s: &'a str = s;
750         s
751     }
752
753     pub fn statik() -> Lifetime {
754         Lifetime("'static".to_string())
755     }
756
757     pub fn elided() -> Lifetime {
758         Lifetime("'_".to_string())
759     }
760 }
761
762 #[derive(Clone, Debug)]
763 pub enum WherePredicate {
764     BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
765     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
766     EqPredicate { lhs: Type, rhs: Type },
767 }
768
769 impl WherePredicate {
770     pub fn get_bounds(&self) -> Option<&[GenericBound]> {
771         match *self {
772             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
773             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
774             _ => None,
775         }
776     }
777 }
778
779 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
780 pub enum GenericParamDefKind {
781     Lifetime,
782     Type {
783         did: DefId,
784         bounds: Vec<GenericBound>,
785         default: Option<Type>,
786         synthetic: Option<hir::SyntheticTyParamKind>,
787     },
788     Const {
789         did: DefId,
790         ty: Type,
791     },
792 }
793
794 impl GenericParamDefKind {
795     pub fn is_type(&self) -> bool {
796         match *self {
797             GenericParamDefKind::Type { .. } => true,
798             _ => false,
799         }
800     }
801
802     // FIXME(eddyb) this either returns the default of a type parameter, or the
803     // type of a `const` parameter. It seems that the intention is to *visit*
804     // any embedded types, but `get_type` seems to be the wrong name for that.
805     pub fn get_type(&self) -> Option<Type> {
806         match self {
807             GenericParamDefKind::Type { default, .. } => default.clone(),
808             GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
809             GenericParamDefKind::Lifetime => None,
810         }
811     }
812 }
813
814 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
815 pub struct GenericParamDef {
816     pub name: String,
817     pub kind: GenericParamDefKind,
818 }
819
820 impl GenericParamDef {
821     pub fn is_synthetic_type_param(&self) -> bool {
822         match self.kind {
823             GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
824             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
825         }
826     }
827
828     pub fn is_type(&self) -> bool {
829         self.kind.is_type()
830     }
831
832     pub fn get_type(&self) -> Option<Type> {
833         self.kind.get_type()
834     }
835
836     pub fn get_bounds(&self) -> Option<&[GenericBound]> {
837         match self.kind {
838             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
839             _ => None,
840         }
841     }
842 }
843
844 // maybe use a Generic enum and use Vec<Generic>?
845 #[derive(Clone, Debug, Default)]
846 pub struct Generics {
847     pub params: Vec<GenericParamDef>,
848     pub where_predicates: Vec<WherePredicate>,
849 }
850
851 #[derive(Clone, Debug)]
852 pub struct Method {
853     pub generics: Generics,
854     pub decl: FnDecl,
855     pub header: hir::FnHeader,
856     pub defaultness: Option<hir::Defaultness>,
857     pub all_types: Vec<(Type, TypeKind)>,
858     pub ret_types: Vec<(Type, TypeKind)>,
859 }
860
861 #[derive(Clone, Debug)]
862 pub struct TyMethod {
863     pub header: hir::FnHeader,
864     pub decl: FnDecl,
865     pub generics: Generics,
866     pub all_types: Vec<(Type, TypeKind)>,
867     pub ret_types: Vec<(Type, TypeKind)>,
868 }
869
870 #[derive(Clone, Debug)]
871 pub struct Function {
872     pub decl: FnDecl,
873     pub generics: Generics,
874     pub header: hir::FnHeader,
875     pub all_types: Vec<(Type, TypeKind)>,
876     pub ret_types: Vec<(Type, TypeKind)>,
877 }
878
879 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
880 pub struct FnDecl {
881     pub inputs: Arguments,
882     pub output: FnRetTy,
883     pub c_variadic: bool,
884     pub attrs: Attributes,
885 }
886
887 impl FnDecl {
888     pub fn self_type(&self) -> Option<SelfTy> {
889         self.inputs.values.get(0).and_then(|v| v.to_self())
890     }
891
892     /// Returns the sugared return type for an async function.
893     ///
894     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
895     /// will return `i32`.
896     ///
897     /// # Panics
898     ///
899     /// This function will panic if the return type does not match the expected sugaring for async
900     /// functions.
901     pub fn sugared_async_return_type(&self) -> FnRetTy {
902         match &self.output {
903             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
904                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
905                     let bindings = trait_.bindings().unwrap();
906                     FnRetTy::Return(bindings[0].ty().clone())
907                 }
908                 _ => panic!("unexpected desugaring of async function"),
909             },
910             _ => panic!("unexpected desugaring of async function"),
911         }
912     }
913 }
914
915 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
916 pub struct Arguments {
917     pub values: Vec<Argument>,
918 }
919
920 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
921 pub struct Argument {
922     pub type_: Type,
923     pub name: String,
924 }
925
926 #[derive(Clone, PartialEq, Debug)]
927 pub enum SelfTy {
928     SelfValue,
929     SelfBorrowed(Option<Lifetime>, Mutability),
930     SelfExplicit(Type),
931 }
932
933 impl Argument {
934     pub fn to_self(&self) -> Option<SelfTy> {
935         if self.name != "self" {
936             return None;
937         }
938         if self.type_.is_self_type() {
939             return Some(SelfValue);
940         }
941         match self.type_ {
942             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
943                 Some(SelfBorrowed(lifetime.clone(), mutability))
944             }
945             _ => Some(SelfExplicit(self.type_.clone())),
946         }
947     }
948 }
949
950 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
951 pub enum FnRetTy {
952     Return(Type),
953     DefaultReturn,
954 }
955
956 impl GetDefId for FnRetTy {
957     fn def_id(&self) -> Option<DefId> {
958         match *self {
959             Return(ref ty) => ty.def_id(),
960             DefaultReturn => None,
961         }
962     }
963 }
964
965 #[derive(Clone, Debug)]
966 pub struct Trait {
967     pub auto: bool,
968     pub unsafety: hir::Unsafety,
969     pub items: Vec<Item>,
970     pub generics: Generics,
971     pub bounds: Vec<GenericBound>,
972     pub is_spotlight: bool,
973     pub is_auto: bool,
974 }
975
976 #[derive(Clone, Debug)]
977 pub struct TraitAlias {
978     pub generics: Generics,
979     pub bounds: Vec<GenericBound>,
980 }
981
982 /// A trait reference, which may have higher ranked lifetimes.
983 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
984 pub struct PolyTrait {
985     pub trait_: Type,
986     pub generic_params: Vec<GenericParamDef>,
987 }
988
989 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
990 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
991 /// importantly, it does not preserve mutability or boxes.
992 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
993 pub enum Type {
994     /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
995     ResolvedPath {
996         path: Path,
997         param_names: Option<Vec<GenericBound>>,
998         did: DefId,
999         /// `true` if is a `T::Name` path for associated types.
1000         is_generic: bool,
1001     },
1002     /// For parameterized types, so the consumer of the JSON don't go
1003     /// looking for types which don't exist anywhere.
1004     Generic(String),
1005     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1006     /// arrays, slices, and tuples.
1007     Primitive(PrimitiveType),
1008     /// `extern "ABI" fn`
1009     BareFunction(Box<BareFunctionDecl>),
1010     Tuple(Vec<Type>),
1011     Slice(Box<Type>),
1012     Array(Box<Type>, String),
1013     Never,
1014     RawPointer(Mutability, Box<Type>),
1015     BorrowedRef {
1016         lifetime: Option<Lifetime>,
1017         mutability: Mutability,
1018         type_: Box<Type>,
1019     },
1020
1021     // `<Type as Trait>::Name`
1022     QPath {
1023         name: String,
1024         self_type: Box<Type>,
1025         trait_: Box<Type>,
1026     },
1027
1028     // `_`
1029     Infer,
1030
1031     // `impl TraitA + TraitB + ...`
1032     ImplTrait(Vec<GenericBound>),
1033 }
1034
1035 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1036 pub enum PrimitiveType {
1037     Isize,
1038     I8,
1039     I16,
1040     I32,
1041     I64,
1042     I128,
1043     Usize,
1044     U8,
1045     U16,
1046     U32,
1047     U64,
1048     U128,
1049     F32,
1050     F64,
1051     Char,
1052     Bool,
1053     Str,
1054     Slice,
1055     Array,
1056     Tuple,
1057     Unit,
1058     RawPointer,
1059     Reference,
1060     Fn,
1061     Never,
1062 }
1063
1064 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1065 pub enum TypeKind {
1066     Enum,
1067     Function,
1068     Module,
1069     Const,
1070     Static,
1071     Struct,
1072     Union,
1073     Trait,
1074     Typedef,
1075     Foreign,
1076     Macro,
1077     Attr,
1078     Derive,
1079     TraitAlias,
1080 }
1081
1082 pub trait GetDefId {
1083     fn def_id(&self) -> Option<DefId>;
1084 }
1085
1086 impl<T: GetDefId> GetDefId for Option<T> {
1087     fn def_id(&self) -> Option<DefId> {
1088         self.as_ref().and_then(|d| d.def_id())
1089     }
1090 }
1091
1092 impl Type {
1093     pub fn primitive_type(&self) -> Option<PrimitiveType> {
1094         match *self {
1095             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1096             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1097             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1098             Tuple(ref tys) => {
1099                 if tys.is_empty() {
1100                     Some(PrimitiveType::Unit)
1101                 } else {
1102                     Some(PrimitiveType::Tuple)
1103                 }
1104             }
1105             RawPointer(..) => Some(PrimitiveType::RawPointer),
1106             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1107             BareFunction(..) => Some(PrimitiveType::Fn),
1108             Never => Some(PrimitiveType::Never),
1109             _ => None,
1110         }
1111     }
1112
1113     pub fn is_generic(&self) -> bool {
1114         match *self {
1115             ResolvedPath { is_generic, .. } => is_generic,
1116             _ => false,
1117         }
1118     }
1119
1120     pub fn is_self_type(&self) -> bool {
1121         match *self {
1122             Generic(ref name) => name == "Self",
1123             _ => false,
1124         }
1125     }
1126
1127     pub fn generics(&self) -> Option<Vec<Type>> {
1128         match *self {
1129             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1130                 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1131                     Some(
1132                         args.iter()
1133                             .filter_map(|arg| match arg {
1134                                 GenericArg::Type(ty) => Some(ty.clone()),
1135                                 _ => None,
1136                             })
1137                             .collect(),
1138                     )
1139                 } else {
1140                     None
1141                 }
1142             }),
1143             _ => None,
1144         }
1145     }
1146
1147     pub fn bindings(&self) -> Option<&[TypeBinding]> {
1148         match *self {
1149             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1150                 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1151                     Some(&**bindings)
1152                 } else {
1153                     None
1154                 }
1155             }),
1156             _ => None,
1157         }
1158     }
1159
1160     pub fn is_full_generic(&self) -> bool {
1161         match *self {
1162             Type::Generic(_) => true,
1163             _ => false,
1164         }
1165     }
1166
1167     pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1168         let (self_, trait_, name) = match self {
1169             QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
1170             _ => return None,
1171         };
1172         let trait_did = match **trait_ {
1173             ResolvedPath { did, .. } => did,
1174             _ => return None,
1175         };
1176         Some((&self_, trait_did, name))
1177     }
1178 }
1179
1180 impl GetDefId for Type {
1181     fn def_id(&self) -> Option<DefId> {
1182         match *self {
1183             ResolvedPath { did, .. } => Some(did),
1184             Primitive(p) => cache().primitive_locations.get(&p).cloned(),
1185             BorrowedRef { type_: box Generic(..), .. } => {
1186                 Primitive(PrimitiveType::Reference).def_id()
1187             }
1188             BorrowedRef { ref type_, .. } => type_.def_id(),
1189             Tuple(ref tys) => {
1190                 if tys.is_empty() {
1191                     Primitive(PrimitiveType::Unit).def_id()
1192                 } else {
1193                     Primitive(PrimitiveType::Tuple).def_id()
1194                 }
1195             }
1196             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1197             Never => Primitive(PrimitiveType::Never).def_id(),
1198             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1199             Array(..) => Primitive(PrimitiveType::Array).def_id(),
1200             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1201             QPath { ref self_type, .. } => self_type.def_id(),
1202             _ => None,
1203         }
1204     }
1205 }
1206
1207 impl PrimitiveType {
1208     pub fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1209         match s {
1210             sym::isize => Some(PrimitiveType::Isize),
1211             sym::i8 => Some(PrimitiveType::I8),
1212             sym::i16 => Some(PrimitiveType::I16),
1213             sym::i32 => Some(PrimitiveType::I32),
1214             sym::i64 => Some(PrimitiveType::I64),
1215             sym::i128 => Some(PrimitiveType::I128),
1216             sym::usize => Some(PrimitiveType::Usize),
1217             sym::u8 => Some(PrimitiveType::U8),
1218             sym::u16 => Some(PrimitiveType::U16),
1219             sym::u32 => Some(PrimitiveType::U32),
1220             sym::u64 => Some(PrimitiveType::U64),
1221             sym::u128 => Some(PrimitiveType::U128),
1222             sym::bool => Some(PrimitiveType::Bool),
1223             sym::char => Some(PrimitiveType::Char),
1224             sym::str => Some(PrimitiveType::Str),
1225             sym::f32 => Some(PrimitiveType::F32),
1226             sym::f64 => Some(PrimitiveType::F64),
1227             sym::array => Some(PrimitiveType::Array),
1228             sym::slice => Some(PrimitiveType::Slice),
1229             sym::tuple => Some(PrimitiveType::Tuple),
1230             sym::unit => Some(PrimitiveType::Unit),
1231             sym::pointer => Some(PrimitiveType::RawPointer),
1232             sym::reference => Some(PrimitiveType::Reference),
1233             kw::Fn => Some(PrimitiveType::Fn),
1234             sym::never => Some(PrimitiveType::Never),
1235             _ => None,
1236         }
1237     }
1238
1239     pub fn as_str(&self) -> &'static str {
1240         use self::PrimitiveType::*;
1241         match *self {
1242             Isize => "isize",
1243             I8 => "i8",
1244             I16 => "i16",
1245             I32 => "i32",
1246             I64 => "i64",
1247             I128 => "i128",
1248             Usize => "usize",
1249             U8 => "u8",
1250             U16 => "u16",
1251             U32 => "u32",
1252             U64 => "u64",
1253             U128 => "u128",
1254             F32 => "f32",
1255             F64 => "f64",
1256             Str => "str",
1257             Bool => "bool",
1258             Char => "char",
1259             Array => "array",
1260             Slice => "slice",
1261             Tuple => "tuple",
1262             Unit => "unit",
1263             RawPointer => "pointer",
1264             Reference => "reference",
1265             Fn => "fn",
1266             Never => "never",
1267         }
1268     }
1269
1270     pub fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1271         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1272     }
1273
1274     pub fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1275         static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1276
1277         CELL.get_or_init(move || {
1278             use self::PrimitiveType::*;
1279
1280             /// A macro to create a FxHashMap.
1281             ///
1282             /// Example:
1283             ///
1284             /// ```
1285             /// let letters = map!{"a" => "b", "c" => "d"};
1286             /// ```
1287             ///
1288             /// Trailing commas are allowed.
1289             /// Commas between elements are required (even if the expression is a block).
1290             macro_rules! map {
1291                 ($( $key: expr => $val: expr ),* $(,)*) => {{
1292                     let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1293                     $( map.insert($key, $val); )*
1294                     map
1295                 }}
1296             }
1297
1298             let single = |a: Option<DefId>| a.into_iter().collect();
1299             let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1300                 a.into_iter().chain(b).collect()
1301             };
1302
1303             let lang_items = tcx.lang_items();
1304             map! {
1305                 Isize => single(lang_items.isize_impl()),
1306                 I8 => single(lang_items.i8_impl()),
1307                 I16 => single(lang_items.i16_impl()),
1308                 I32 => single(lang_items.i32_impl()),
1309                 I64 => single(lang_items.i64_impl()),
1310                 I128 => single(lang_items.i128_impl()),
1311                 Usize => single(lang_items.usize_impl()),
1312                 U8 => single(lang_items.u8_impl()),
1313                 U16 => single(lang_items.u16_impl()),
1314                 U32 => single(lang_items.u32_impl()),
1315                 U64 => single(lang_items.u64_impl()),
1316                 U128 => single(lang_items.u128_impl()),
1317                 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1318                 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1319                 Char => single(lang_items.char_impl()),
1320                 Bool => single(lang_items.bool_impl()),
1321                 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1322                 Slice => {
1323                     lang_items
1324                         .slice_impl()
1325                         .into_iter()
1326                         .chain(lang_items.slice_u8_impl())
1327                         .chain(lang_items.slice_alloc_impl())
1328                         .chain(lang_items.slice_u8_alloc_impl())
1329                         .collect()
1330                 },
1331                 Array => single(lang_items.array_impl()),
1332                 Tuple => smallvec![],
1333                 Unit => smallvec![],
1334                 RawPointer => {
1335                     lang_items
1336                         .const_ptr_impl()
1337                         .into_iter()
1338                         .chain(lang_items.mut_ptr_impl())
1339                         .chain(lang_items.const_slice_ptr_impl())
1340                         .chain(lang_items.mut_slice_ptr_impl())
1341                         .collect()
1342                 },
1343                 Reference => smallvec![],
1344                 Fn => smallvec![],
1345                 Never => smallvec![],
1346             }
1347         })
1348     }
1349
1350     pub fn to_url_str(&self) -> &'static str {
1351         self.as_str()
1352     }
1353 }
1354
1355 impl From<ast::IntTy> for PrimitiveType {
1356     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1357         match int_ty {
1358             ast::IntTy::Isize => PrimitiveType::Isize,
1359             ast::IntTy::I8 => PrimitiveType::I8,
1360             ast::IntTy::I16 => PrimitiveType::I16,
1361             ast::IntTy::I32 => PrimitiveType::I32,
1362             ast::IntTy::I64 => PrimitiveType::I64,
1363             ast::IntTy::I128 => PrimitiveType::I128,
1364         }
1365     }
1366 }
1367
1368 impl From<ast::UintTy> for PrimitiveType {
1369     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1370         match uint_ty {
1371             ast::UintTy::Usize => PrimitiveType::Usize,
1372             ast::UintTy::U8 => PrimitiveType::U8,
1373             ast::UintTy::U16 => PrimitiveType::U16,
1374             ast::UintTy::U32 => PrimitiveType::U32,
1375             ast::UintTy::U64 => PrimitiveType::U64,
1376             ast::UintTy::U128 => PrimitiveType::U128,
1377         }
1378     }
1379 }
1380
1381 impl From<ast::FloatTy> for PrimitiveType {
1382     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1383         match float_ty {
1384             ast::FloatTy::F32 => PrimitiveType::F32,
1385             ast::FloatTy::F64 => PrimitiveType::F64,
1386         }
1387     }
1388 }
1389
1390 impl From<hir::PrimTy> for PrimitiveType {
1391     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1392         match prim_ty {
1393             hir::PrimTy::Int(int_ty) => int_ty.into(),
1394             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1395             hir::PrimTy::Float(float_ty) => float_ty.into(),
1396             hir::PrimTy::Str => PrimitiveType::Str,
1397             hir::PrimTy::Bool => PrimitiveType::Bool,
1398             hir::PrimTy::Char => PrimitiveType::Char,
1399         }
1400     }
1401 }
1402
1403 #[derive(Clone, PartialEq, Eq, Debug)]
1404 pub enum Visibility {
1405     Public,
1406     Inherited,
1407     Crate,
1408     Restricted(DefId, Path),
1409 }
1410
1411 #[derive(Clone, Debug)]
1412 pub struct Struct {
1413     pub struct_type: doctree::StructType,
1414     pub generics: Generics,
1415     pub fields: Vec<Item>,
1416     pub fields_stripped: bool,
1417 }
1418
1419 #[derive(Clone, Debug)]
1420 pub struct Union {
1421     pub struct_type: doctree::StructType,
1422     pub generics: Generics,
1423     pub fields: Vec<Item>,
1424     pub fields_stripped: bool,
1425 }
1426
1427 /// This is a more limited form of the standard Struct, different in that
1428 /// it lacks the things most items have (name, id, parameterization). Found
1429 /// only as a variant in an enum.
1430 #[derive(Clone, Debug)]
1431 pub struct VariantStruct {
1432     pub struct_type: doctree::StructType,
1433     pub fields: Vec<Item>,
1434     pub fields_stripped: bool,
1435 }
1436
1437 #[derive(Clone, Debug)]
1438 pub struct Enum {
1439     pub variants: IndexVec<VariantIdx, Item>,
1440     pub generics: Generics,
1441     pub variants_stripped: bool,
1442 }
1443
1444 #[derive(Clone, Debug)]
1445 pub struct Variant {
1446     pub kind: VariantKind,
1447 }
1448
1449 #[derive(Clone, Debug)]
1450 pub enum VariantKind {
1451     CLike,
1452     Tuple(Vec<Type>),
1453     Struct(VariantStruct),
1454 }
1455
1456 #[derive(Clone, Debug)]
1457 pub struct Span {
1458     pub filename: FileName,
1459     pub cnum: CrateNum,
1460     pub loline: usize,
1461     pub locol: usize,
1462     pub hiline: usize,
1463     pub hicol: usize,
1464     pub original: rustc_span::Span,
1465 }
1466
1467 impl Span {
1468     pub fn empty() -> Span {
1469         Span {
1470             filename: FileName::Anon(0),
1471             cnum: LOCAL_CRATE,
1472             loline: 0,
1473             locol: 0,
1474             hiline: 0,
1475             hicol: 0,
1476             original: rustc_span::DUMMY_SP,
1477         }
1478     }
1479
1480     pub fn span(&self) -> rustc_span::Span {
1481         self.original
1482     }
1483 }
1484
1485 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1486 pub struct Path {
1487     pub global: bool,
1488     pub res: Res,
1489     pub segments: Vec<PathSegment>,
1490 }
1491
1492 impl Path {
1493     pub fn last_name(&self) -> &str {
1494         self.segments.last().expect("segments were empty").name.as_str()
1495     }
1496 }
1497
1498 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1499 pub enum GenericArg {
1500     Lifetime(Lifetime),
1501     Type(Type),
1502     Const(Constant),
1503 }
1504
1505 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1506 pub enum GenericArgs {
1507     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1508     Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1509 }
1510
1511 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1512 pub struct PathSegment {
1513     pub name: String,
1514     pub args: GenericArgs,
1515 }
1516
1517 #[derive(Clone, Debug)]
1518 pub struct Typedef {
1519     pub type_: Type,
1520     pub generics: Generics,
1521     // Type of target item.
1522     pub item_type: Option<Type>,
1523 }
1524
1525 impl GetDefId for Typedef {
1526     fn def_id(&self) -> Option<DefId> {
1527         self.type_.def_id()
1528     }
1529 }
1530
1531 #[derive(Clone, Debug)]
1532 pub struct OpaqueTy {
1533     pub bounds: Vec<GenericBound>,
1534     pub generics: Generics,
1535 }
1536
1537 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1538 pub struct BareFunctionDecl {
1539     pub unsafety: hir::Unsafety,
1540     pub generic_params: Vec<GenericParamDef>,
1541     pub decl: FnDecl,
1542     pub abi: Abi,
1543 }
1544
1545 #[derive(Clone, Debug)]
1546 pub struct Static {
1547     pub type_: Type,
1548     pub mutability: Mutability,
1549     /// It's useful to have the value of a static documented, but I have no
1550     /// desire to represent expressions (that'd basically be all of the AST,
1551     /// which is huge!). So, have a string.
1552     pub expr: String,
1553 }
1554
1555 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1556 pub struct Constant {
1557     pub type_: Type,
1558     pub expr: String,
1559     pub value: Option<String>,
1560     pub is_literal: bool,
1561 }
1562
1563 #[derive(Clone, PartialEq, Debug)]
1564 pub enum ImplPolarity {
1565     Positive,
1566     Negative,
1567 }
1568
1569 #[derive(Clone, Debug)]
1570 pub struct Impl {
1571     pub unsafety: hir::Unsafety,
1572     pub generics: Generics,
1573     pub provided_trait_methods: FxHashSet<String>,
1574     pub trait_: Option<Type>,
1575     pub for_: Type,
1576     pub items: Vec<Item>,
1577     pub polarity: Option<ImplPolarity>,
1578     pub synthetic: bool,
1579     pub blanket_impl: Option<Type>,
1580 }
1581
1582 #[derive(Clone, Debug)]
1583 pub enum Import {
1584     // use source as str;
1585     Simple(String, ImportSource),
1586     // use source::*;
1587     Glob(ImportSource),
1588 }
1589
1590 #[derive(Clone, Debug)]
1591 pub struct ImportSource {
1592     pub path: Path,
1593     pub did: Option<DefId>,
1594 }
1595
1596 #[derive(Clone, Debug)]
1597 pub struct Macro {
1598     pub source: String,
1599     pub imported_from: Option<String>,
1600 }
1601
1602 #[derive(Clone, Debug)]
1603 pub struct ProcMacro {
1604     pub kind: MacroKind,
1605     pub helpers: Vec<String>,
1606 }
1607
1608 #[derive(Clone, Debug)]
1609 pub struct Stability {
1610     pub level: stability::StabilityLevel,
1611     pub feature: String,
1612     pub since: String,
1613     pub unstable_reason: Option<String>,
1614     pub issue: Option<NonZeroU32>,
1615 }
1616
1617 #[derive(Clone, Debug)]
1618 pub struct Deprecation {
1619     pub since: Option<String>,
1620     pub note: Option<String>,
1621     pub is_since_rustc_version: bool,
1622 }
1623
1624 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1625 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1626 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1627 pub struct TypeBinding {
1628     pub name: String,
1629     pub kind: TypeBindingKind,
1630 }
1631
1632 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1633 pub enum TypeBindingKind {
1634     Equality { ty: Type },
1635     Constraint { bounds: Vec<GenericBound> },
1636 }
1637
1638 impl TypeBinding {
1639     pub fn ty(&self) -> &Type {
1640         match self.kind {
1641             TypeBindingKind::Equality { ref ty } => ty,
1642             _ => panic!("expected equality type binding for parenthesized generic args"),
1643         }
1644     }
1645 }