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