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